Custom codegen for SDKs

Show Notes

In this episode of Build and Learn, we discuss code generation (codegen) and how Stripe uses it to generate SDKs for its APIs automatically. We talk about how a declarative shape of an API (such as Open API spec or GraphQL schema) can be fed into a tool to generate an SDK in a specific programming language. This process helps ensure that the SDKs are always in sync with the API and that any changes to the API are automatically reflected in the SDKs. 

Most SDKs today are still hand-written, but automatic generation is becoming more popular. 
We'll touch on the tradeoff between readable code and automatically generated code, which can be quite long and complex.  
You'll also hear how the Ruby clients for Orbit were likely written by hand and may not be up-to-date.

Resources:
  • Richard Marmorstein's Strangeloop talk about codegen: https://www.youtube.com/watch?v=mgRreyw-Nlg
  • CJ's RubyConf 2022 talk about codegen: https://www.youtube.com/watch?v=sm0fgIqfsO8
  • Stainless API company: https://stainlessapi.com/
  • Open API Spec: https://swagger.io/specification/ 
  • Stripe API Spec: https://github.com/stripe/openapi
  • Swagger codegen: https://swagger.io/tools/swagger-codegen/ 
  • Orbit Ruby Activities gem: https://github.com/orbit-love/ruby-orbit-activities


Full Transcripts

CJ: In this episode, Colin and I talk about cogen and how we use Cogen at Stripe. We'll also mention a conference talk at Ruby Conf. That already happens, so if you're curious and you wanna see that, head over to the description and we'll have a link for you. Enjoy the show.

Colin: Welcome to Build and Learn. My name is Colin.

CJ: And I'm cj, and we weren't gonna record today, but we're suddenly both free

Colin: Yep.

CJ: Yeah, Twitter was gonna have a developer conference called chirp, but it's canceled. The entire conference is canceled.

Colin: It is canceled. Yeah, we, I think we talked about it a few episodes ago where we were pretty excited to see, uh, Twitter getting back to its developer roots, and they kind of burned to the developer community a few times over the last decade or more. And this was looking like a good sign that that would be different. So if you're listening to this in 2023, you already know about all this, but obviously Elon bought Twitter what, in October? , I wouldn't have wanted to necessarily be at that conference working at Twitter and having to answer questions, right? Like, imagine being a dev advocate, right? and being asked all these questions that you don't have answers to.

CJ: Right. I don't think there are any more develop, like all of the people. at Twitter who were on the developer advocacy team that I was interacting with. I don't know any of them that are still there. Like, uh, half of them or more were laid off in the first round. Some of them quit shortly after, and I think the rest took the. Opportunity to bail when Elon was like, Hey, if you don't want to be here and grind it out, then like, you can, here's the door , and they

Colin: Yeah, he sent everyone that email of, do You Like Me? Yes or no? Right.

CJ: yeah. Circle yes or no.

Colin: uh, so, so chaotic, I think. Yeah. Chris Mesina tweeted that it was like 97% of the, I don't know if it's, he said platform, so I don't know if that means developer platform and in like even the developers. of the platform, including the developer, obviously team are just not there anymore. So that's gonna be interesting to see where it goes.

CJ: Yeah. There's also just a ton of people going out in like flames of glory , you know, like just calling out Elon on Twitter for showing bad charts or using bad metrics or, saying like, oh, I think he said something like, oh, the A the app is slow in certain countries because it's doing thousands of RPC calls. And then someone was like, not true. I've been working on this for like six years and , you know, blah, blah, blah. And then, you know, five seconds later that person's fired. Just today I was watching some tos where people were like counting down until they got locked out. And then, you know, they had champagne ready to go when they got locked outta their laptops and stuff.

Colin: I mean, even, uh, Justin Jackson was sharing some tweets today about how, like there's been on some news posts that came out this morning about how the building is locked down again and no one can get in. And then he shared a tweet from someone who used to run their access control and that Elon's calling him back to help, like they're all locked out of the building and that he needs help getting back into the building. It's like, oh man. , I don't know. He should have bought it and not touched it, I think is what it's like. It's like a no make, don't make any big decisions right after you make a big purchase decision. It's like

CJ: Yeah. The way that I've been thinking about it is that, He has started or made big influential moves on the cultures of Tesla and SpaceX and all these other companies when they were really in their infancy. And so the people I know who work at SpaceX or worked at SpaceX made the conscious decision when they joined SpaceX. To sleep in their van in the parking lot because they knew they were gonna have to work like 90 hours a week. But they did that because they wanted to be part of like this thing that he was building. But on the other hand, there was like all of these people at Twitter who I think were like really happy with the quality of life and they chose Twitter for, the community and like all of these, great work-life balance benefits and, working remotely and all this stuff. And then he comes in and shifts the culture from the top down and you. , 80% of the people who worked there didn't want to work in that environment, and so it just kind of like blew up in his face a bit. But

Colin: Well, and I think the rhetoric right now is that they don't wanna work hard. And it's just a different culture. It's like there are definitely people who got let go, who know how Very, very specific things inside of Twitter were. And now no one will know how those things work. And sure, that might be bad documentation or whatever, but like I'm looking at my Twitter right now. I've been on Twitter since March of 2007. There is more than 15 years of culture that has already been developed, at Twitter. If people have been there fr since that time. Some people have been there only a few years, but You could probably look around at all the tech layoffs and realize that yeah, everyone probably overhired since the pandemic started. Just wholesale cutting half of your team, your company because you bought something with a bunch of debt is gonna have some waves for sure. And I think everyone's trying to figure out like, how do you make money? And like we, we pay for Twitter's api like. I don't think a lot of people know that there is a paid offering for the a p I. And I think some people were like making calls on Twitter for like, make the a p I fully open again and let us make as many calls as we want. And it's does anyone remember what it was like when that was the case? Like fail whale was prevalent. It wasn't a reliable api. I, the guy who works, or probably the team now that works on. Tweet bot, you know, I've followed him for years and just watched like their issues. Cause they even were like limited to the number of API keys. They were allowed. And so it's like when you buy Tweetbot, you get one of our hundred thousand p i keys and only a hundred thousand people can use our Twitter client. It's like in what world is that normal

CJ: Mm-hmm. . Part of his thing early on was like, there's too many bots on Twitter, and so I could see him arguing for just shutting the whole API down. Like, you have to be a human That's on the app that's tweeting and we're only gonna let that. Fly and not let people have API access. But gosh, I don't want that to be the world.

Colin: true. And that's something that I'm paying attention to cuz we integrate heavily with Twitter at orbit, right? So I'm like, okay, what does this mean for us? And some people are asking us for Mastodon, integration now, and we're looking at that. But like some people, I still, I looked at the API and it's pretty similar. but, and this will get us into our topic today, but the, the tricky thing is it's just not a really mature set of tools around it. And Mastodon servers are just melting right now because people don't know how to host Mastodon. People are realizing that a centralized service with a whole DevOps team, it turns out, is pretty important. Instead of a bunch of, ma on fail whales,

CJ: So you are, are you on Macedon, like as a user?

Colin: Yeah, I joined the Ruby Social one, so ruby.social. Um, I like it, you know, it's a little, it's definitely rough. You can tell it's an open source project.

CJ: Yeah. .is it is it like implemented with Ruby? Is it the Rails app? Do you know? Like,

Colin: I actually don't know. Um,

CJ: Because there was someone who posted in the Ruby social Mastodon main feed or whatever. also, I don't know what the terms are, . I'm still trying to figure out what, like this

Colin: Those toot toots,

CJ: yeah, you gotta make some toots, someone tooted and, uh, , their toot was about how like there's all these issues on one of the master on repos and they were basically making a call to action for all the rubus that were in ruby.social to help maintain it. I was like, is this thing like implemented in Ruby? I don't know.

Colin: Well, I think, uh, Mike from Sidekick runs the Ruby Social one. Um, yeah, so if anyone knows how to scale things, I think he's gonna be pretty set there. But yeah, I'll have to check and see. It'd be interesting. Maybe we, we should do a, a chat and maybe even we find someone who's more familiar with Mastodon to talk about it in the next episode. Actually getting Mike on the show would be really good too. Just talk about sidekick stuff eventually. But with all that said, like there is an API for Mastodon. When we get into working with APIs, we can work with those like raw and make API calls, but most of us are using SDKs and you're actually gonna be doing a talk. I guess the talk will have happened when this episode comes out, but, uh, it'll probably be released on YouTube a little bit after this podcast comes out. So, um, let's dive into s TK Generation and kind of what you're gonna be chatting about at Ruby Comps.

CJ: Yeah. So a lot of times if you're implementing an api, , you can have the API spit out an artifact that has like the shape of the api. A lot of times it's like the open API spec. Are you are, do you have the open API spec for Orbit? Uh,

Colin: Yeah, we use, uh, open api, which I think is the same as swagger these days. Right. It's, yeah.

CJ: Swagger. I think Swagger got like renamed to open api.

Colin: Exactly. Yeah.

CJ: So it could be open API speck, or it could be, I think jsun API is another one. And then, uh, or you could have like G R P C proto buff, like your proto buff schema definitions. Could be like another artifact, but basically you just want like, or even in, in GraphQL too, right? The GraphQL schema. All of these are versions of some. Sort of declarative thing that gives you the shape of your api. And it's usually like, what are the endpoints, what are all the different parameters it expects what's required and not required. And what you can do is take that spec and then run it through a tool to generate and spit out an sdk. And if we really wind back the clocks to, talking about like XML APIs. Then, I don't know, did you ever have to work with those SDS

Colin: I had to do. I had to do soap APIs with wisdom files. Yeah.

CJ: Yes, yes. Yeah. So, uh, way back in the day. , this is like Prej, S o uh, a lot of APIs were implemented with xml, and we had to do this at my VR with, some of the big booking engines or like listing platforms. They, they didn't have JS O APIs. They had XML APIs, and you could get an X S D, which is a XML schema definition, which is similar to an open API spec or any of these things. but then there were tools that could take this schema definition and generate bindings or an sdk, client library, whatever, in a given programming language. So in that case, we were, you know, taking x sd, converting it to Python. Um, and for the Stripe api we spit out the open API spec. And then we have this really, really badass tooling that takes the Open API spec and generates all seven of our official support. Server languages like the SDKs for all of those languages. So Ruby, Python, PHP, node, go Java and.net. We have Stripe SDKs for all of those languages and they're all now automatically generated using the open API spec. And I like, I know that I've used Orbit Ruby or some sort of Ruby clients for Orbit. Are those also generated or are those main maintained by hand?

Colin: You know, I think they were written by hand and I would say they're not maintained, so

CJ: Oh, they're not maintained at all.

Colin: like, I haven't touched them since I've been here. So, and yeah, the folks who built them don't work here anymore. So I think this is one of those things where, you know, I wrote down here like, what does SDK generation help to solve? Because the a API I has changed, right? And so we get to spit out at this new artifact of a new spec, a new open API doc. And it would be really nice to have that always be in sync right now. Once that changes, the docs need to be updated and the SDKs need to be updated. And then you need to communicate those SDK updates. You know, if it's a gem, if it's a MPM module, those need to make it out as as version changes, you know, whether they're breaking or non breaking changes. Do you think that most s STKs today are done automatically, or do you think that a lot of people are still handwriting.

CJ: I. . So there's a, there is an interesting trade off when you're looking at Generat like automatic generation, and that is like if you want your SDK to be readable, then using the automatic generation tools don't really generate very readable code. And so if you just take like the open API spec and you run it through the Swagger Code Gen or the Open API code cogen stuff, it spits out like a giant, huge library. it's automatically generated, but it's really tough to use. Um, and so your trade off is like, do we want to use the automatic generation and have like a really tough to use tool or do we wanna write our own or do we want to like build our own generation tooling that does like a hybrid of both?, so that's the tooling that I'm excited to share and talk about is like this hybrid of, of both worlds where we've, we've built this pipeline, but. The whole point of SDK generation is to make sure that your s like all of your client libraries are staying up to date with the api. And so, yeah, going back to the top of the show, right, you're talking about how like, yeah, we might just make API calls directly to the API using Curl or Postman or something like that. But when we're integrating that into our applications, we're gonna be using Ruby code or JavaScript code or whatever to make those API calls. One option is to write your own like class that represents a client of the API and then use, HTP party, rest client, whatever sort of built-in library there is for making HTP calls or to use a library that is provided by the third party to integrate with. For instance, transistor, the host, the podcast host that we have for this platform, I found like an unofficial community, Ruby Library for it. And I was like, ah, I don't think so. . And so, um, I want to add a list of all of our podcasts to my website. I was like, oh, I'll just use the transistor API and you can like get an API key. And so I just built, I wrote a class, very simple transistor RV like Ruby class. , has a couple of helper methods on it that will just make the request to fetch all the episodes and page and iterate over those. So that's the trade off between the two is right, like you're gonna either have, um, no, no SDK and you're expect your all developers to go and implement all of those helper methods themselves. Or you have an SDK that's auto-generated by a really generic. Platform like swagger, cogen, you end up with this massive, huge library that is like really hard to read. Or the third option is that you build your own generation tooling.

Colin: And when you say it's hard to read, you're talking like, I mean now it's just as hard, like you're, you're having to reference the docs all the time because it's not nece, it's machine readable. It's not necessarily like a, an amazing developer experience.

CJ: exactly. To make this more concrete. If you take the Open API artifacts that are spit out for the Stripe API and you run it through swagger, cogen, one of the. Like wrapper classes it gives you is 30,000 lines of Ruby code. And then for every single resource in the API and all of its like sub resources, it will generate CL classes and files and there's like 2,200 files. So it's like you're either reading through this ridiculously massive like file or like thousands of files to try to figure out, you know, how do I construct an API call with the right classes and the right methods and things like that. And so,

Colin: right? Because you do also have to have like docs for this new client library too. When. Could build that. Right? And Stripe is infamous for having very good docs and, very human readable, SDKs. And I think a lot of people think that to get there, you have to have this huge docs team and this huge s STK team and that you're gonna write everything bespoke. But you guys have kind of fallen in that happy middle of generation plus some hybrid, is that custom handwritten stuff that's being done in the middle there?

CJ: So, Yes, and for a long time, for like seven plus years, we manually maintained and hand wrote all the SDKs. So when a new feature would land in the api, there was a Slack notification and then, these volunteers would jump in and start making prs to all of the different SDKs in publishing, publishing those. And that would take several hours, sometimes a full day of. To add the features, especially to Stripe, Java, like Java's just so verbose that you know, if you change an eum, you've gotta go change and update like six files in Stripe, Java. And so we built this layer. It took two years to migrate all the SDKs to, and the other thing was that we were trying to build the generation so that it mirrored what the handwritten versions were before. So like you've gotta back into your existing patterns. And so we built this f. Uh, this guy Alex Ratray, he runs a company called stainless.dev that does this like SDK generation and developer experience as a service now. So you can like hire stainless.dev. And, uh, he built like the first versions of this tool that we use internally called Prettier Poet. And Prettier poet is a react like framework where you. Components that are language specific, and they give you things like method calls or, you know, literals or strings or, uh, as like, you know, in instance, variable assignment or class definitions. So you can use these, language specific ones. They also have like all the tooling for comments. And then when you build Your high level react component. You can use the open API spec as the data. That's kind of like your original data tree. That's the input into that. And so you can generate all the classes. So in the Stripe api, there's like customers and subscriptions and payment intents. Those are all defined in the open API spec. You can like iterate overall the resources in the open API spec and have those feed into this React component that is gonna be like, oh, this is the resource component and it knows how to generate the class. And then it can use the spec to know like what's the class name and what are all the methods and what are my, what are the documentation strings that should be added to the top of the class and to each of the methods and. What's really cool about this is that like at first we did it just for SDK generation, but now we have like this tooling that generates the Postman client. It generates the API reference. All of the code snippets that you see in the docs we're generating like tons and tons of those with this like higher order markdoc.dev component called cogen snippet, where you basically say like, okay, this is a, an api. To v1/customers it's a post request and here's the arguments, and that will spit out the code in all seven languages. It shows the code in curl, it shows how to do it with Stripe cli, and that's like all autogenerated now. And before that was all like just string and interpolation in erb files, so

Colin: Wow. Yeah. I was gonna ask, because it sounds very similar to Mark Docs, so you guys have Mark Docs and your SDKs are being fed by this generation, if I'm, if I'm thinking of the trees properly. Right. So you have your open API spec, which then, feeds into prettier poet and then. Generates those, those artifacts, fors, stk, STKs, and your docs.

CJ: Yeah, exactly. And even things like, we have a visual studio code extension. So if you install like the stripe for VS code extension, then you get. Snippet completion. So you can type like stripe payment intent, create and hit tab, and that will auto complete a snippet in vs code. Like that's also powered by this thing. And so, uh, I think even like the stripe shell, so if you go to the documentation and you hit like tilde or whatever, it pops open a little drawer at the bottom that lets you have this interactive shell for making API calls directly in the docs. And all of that is backed by,

Colin: Wait, this. is, this is in the docs that you

CJ: Yeah, if you go to like stripe.com/docs and then hit . Yeah. Hit like, you know, back tick or whatever, it should pop open. Stripe Shell which is like a browser-based version of the Stripe c l

Colin: Oh, wow. Yeah. we're finding out all the secrets today. Yeah. The other one we just found, if you go to the, uh, if you just go to customer.new or do you know about this one?

CJ: No. What is customer not new?

Colin: If you go to customer.new as a, as a u r url, it launches into Stripe and tries to create a new customer if you're logged into Stripe. Yeah, we've just found that cuz we also, we have member new for Orbit, so if you just like even make a bookmark for member.new. And click on it. It just launches a little screen to add a new member to your workspace. But um, I think a lot of people are start, there's like a whole list of all the ones that you can do around the web now. I'm sure there's like a notion, page.new or something out there, but

CJ: so I definitely knew. Okay, so invoice.new works, subscription.new. Works. So there were a couple that I knew about, I did not know about customer New .

Colin: Yeah, it's whatever company gets to the TLD before anyone else because Now no one else can do subscription.new, only, only Stripe powers that. But yeah, fun little Easter eggs for the internet. I'm trying to think if we have any other ones for, but I'll have to share that console with, uh, with uh, Alex who works on a lot of our Stripe stuff. And even the, I didn't know that there was a VS code extension, you know, cause in my mind I was trying to think of like how all this is really exciting when you think about even the open API spec teaching. GitHub co-pilot, right? Like, just being able to be like, I don't want to go, always look at the docs for every little thing, but like GitHub co-pilot or Stripe cli, or Stripe, you know, vs. Code extension helped me with what I'm working on here. And when I've used s STKs, like some SDKs are just as. Like, I would rather go just do curl calls or like http party or something like that, because I know what I'm doing., there are some amazing ones. I'm betting that the Discord one is probably auto-generated, but what's really cool is that like once you get the table stakes of just good s stk generation done, the discord, client libraries also help you. Rate limiting like automatically. Um, and it's, so it's got a bunch of like Texs and like backgrounding that happens to make sure that you're, like, you're not writing the code yourself to make sure you're staying within those rate limits, which is really nice. But you probably don't get to work on stuff like that if you're having to hand write these things every single time that the API changes. And then you get the drift. I mean honestly this conversation's inspiring me to, go look at our Ruby. I think we have a Ruby one and a JavaScript one, and I think that's probably it. Um, but I do know that the JavaScript one, it's like very opinionated and I think that's the challenge. It's like whoever wrote that one, that's how you. It's not necessarily how you might write it or how I might write it. And so there's like that kind of like an opinion about the developer experience instead of just saying taking a customer object, if there's a class for it, and being able to like add an invoice really easily and let it fill in all the parameters for customer and do all that stuff behind the scenes. Or do you have to go build each object by hand and then send it to the client in order to save those things?

CJ: Right, and I think sometimes what's interesting about building this. generation layer is say that you make a choice early on when you're building the SDK that you want to have people interact with the API through like class methods on some resource, right? So you have like Stripe::Customer.Create and that takes in some a hash that will like pass those arguments to the api, but later you decide that, oh, it's actually way better if instead of having these class methods globally available, That we have a client where you can like new up and say like, Stripe know, stripe.new, and then you call like stripe.customers.Create And so what's crazy is like you can use the, these like generation layer to implement both patterns and then you can slowly start migrating people over to this new pattern or just enable both. Both like methods and. If you look right now, there's definitely parts of the stripe docs that are still one foot in the old world for like some of the SDKs, like php, where we had all of the. Documentation written as class methods, but the API ref and all of the auto-generated snippets are now migrated over to this like client and services pattern. And so that is definitely one of the benefits. But yeah, if, if your original authors took like one approach that you disagree with and you don't wanna break everyone, then it's ki it can be challenging to like, Release a new pattern and have everyone upgrade or,

Colin: yeah. just alias. Alias everything. Yeah.

CJ: Yeah, exactly.

Colin: I think one of the considerations that I've heard with SDK generation is if you're not a rubus, for example, and a Java person writes a Ruby client library, right? It's probably not gonna follow. Ruby conventions. And so like, this is something to consider in your sstk generation, is that these tools probably should know a little bit about the standards in Java look like this and Python looks like this. Even just variable naming and stuff like that. Class names Camel Case, you know, snake Case, all those kinds of things where you can tell they're like, oh, a Java person wrote this. Or a JavaScript person type script, whatever it looks like. I'm just trying to think through like pros and cons here. It sounds like, you probably have more contained like testing and continuous deployment and being able to have failures and tests and all that kind of stuff along the way.

CJ: totally. Yeah. So what's cool is that if you have patterns built into the api, then you can test your generation layer and be pretty confident that it's gonna spit out the right code. And if it's spitting out the wrong code, then you can fix it at the generation layer and that will fix it all, like in all the downstream places. So it fixes the docks and it fixes the SDKs and it fixes kind of everything ideally. But yeah, it's, it's also important I guess to mention that like we're taking the open API spec and by itself using the spec was really challenging in order to go from like this giant J s O object into all of these SDKs and client libraries and whatever. And so there is this like intermediate step that we call, like compiling the open API spec into this thing called Stripe type. And so I th we initially started with Flow, but I think we're using Ty, uh, type script now, where we take the, uh, the original j s o blob that came out of the open API spec, and then we build all of these different like discriminated types for what the high level resources should all look like. And then we use that as our input into prettier poet and our input into all these docs tools. That way we have this much. More like strongly typed and wired up tool because the, the Open API spec will actually give you back the resource and here's the methods, but also like down here is in a separate area. Here's the responses, and you kind of need to combine both of those in order to have all the information to implement a strongly typed language. Go and see Sharp or whatever. And there is that intermediate step and if people are interested in, learning more about that, Richard from our team did a talk at Strange Loop last year, and so we'll put a link to that, uh, on YouTube. And it's super interesting to watch, how that evolved. But yeah, when you were, when you were talking about how, like, like snake case versus Camel case versus whatever, have you ever used a Ruby motion? Ruby Motion, like.

Colin: I'm.

CJ: Okay, so there was, I think, 20 12, 20 13 or something, you could use Ruby to implement like iOS apps and it had like some tooling to spit out. I, it must have been like objective C or something like this, but it was so funny because the class ne like the class names would be like, you know, application on a knit with whatever. You know, and completion block or whatever, , like kind of the apple, the apple like, uh, objective seed name for the method. But it was just like in Ruby, so it was like deaf and then like this 85 character method name. But I think probably, uh, everyone who's been around for a while has encountered some SDK where you're like, this is not, this was not like implemented by Rubus based on all the different weird names and stuff that are.

Colin: But I, what I like is that everything is then in code. You can commit, you can add to a change log. The change log goes out to all the different s STKs. So does that mean that you guys release, when you release an update to one s stk, you always release an update to all of them? Or is there some like, yeah, so there's not really like, oh, we're only gonna bump one because it affects all of them.

CJ: Yeah, so we will release. So there are some changes that only impact the strongly typed languages because we do use some meta programming for some things. And so like if there is a change to an eum, like there's already an existing eum and we're just adding like a new value for that enum or something, then it only needs to change. Java go.net and the type definitions for Stripe node, but it doesn't need to change Ruby or Python or PHP because those are all just gonna say like, ah, you give me a string, you give me a string. It must work . Because they're not like checking types or anything, As soon as a feature is generally available, it kicks off this domino chain that is pretty wild. Like it will automatically generate like all the internal versions of it and tests and snapshot tests and like all of this stuff. And then it will also kick off the Slack message. And then the S STKs team goes and runs like generate, generate, generate, generate on all the SDKs. And that all makes prs and those prs get reviewed. And once those are merged, those all get deployed out to like, you know, Ruby Gems and npm. Maven and Gradle and whatever. It's interesting to be the person that's gonna tick the box that says this is generally available now. And it's like, you can't take that back very easily.

Colin: Yeah, I was thinking like as a small company or a smaller company, it's like, whew, we're gonna be running a lot of, we're gonna run a lot of servers and spend a lot of money right now when we took this box and a lot of prs and CDs are gonna fire up and you're gonna get a bunch of servers running a bunch of code and now we got a bunch of PRS to review and yeah, it's pretty

CJ: Yeah, that all that said, like I think it is really valuable and important to have features immediately available in the SDKs because that is like the main way that devs are using and feeling stripe, right? They're like, Their first impression is, okay, I installed Stripe, Ruby, and then I tried to make a customer or something like that. Like usually they're not, interacting with the Stripe API directly. The actual numbers of people who . Are using the Stripe API directly through official SDKs is massive. Like, it's surprising how many people use the SDKs instead of just making raw requests.

Colin: Well, I mean, with Stripe there's so many requests that you need to chain together, right? To do some things. So I feel like that one makes a lot of sense. Cause a lot of people aren't used to, you know, carrying around all the responses and like, let's make this call. Like I've done the, like, you know, do the full process of checking somebody out in Postman, right? And it's like, okay, it's good to know how it works, but man, a library really. A lot more sense for this one, right? With Orbit, it's like, okay, sending an activity is just one call. Now talking and pulling data outta orbit requires a lot of chaining of APIs, calls to get IDs and stuff like that. And some of the things we're thinking about is like, how do we, I really like when APIs have like the side loading. I think you guys have that with yours where you can say like, This is an id, but I want it to be the full object. I don't want the ID of it. I want the customer with the invoice attached and those kinds of things I'd really like us to have. Cause right now it's like, here's an organization id, you go get the organization that it's attached to and make another call when we already know who that is and all that. I think the thing that we're not talking about here that we should probably talk about in a future episode is that like, This assumes you have an open API spec and that you have like a well designed api. Like this isn't designing your API for you. This is just the tooling around your api. And you know, I've been thinking of what RV two API I looks like so that we can get a, a different API spec cuz our a p is a J S O N api and it turns out J S O API is really good for like machine to machine computers understand it. I mean it's most of these right? Like a soap api. Has a wisdom, like you were talking about these X S D bindings, um, all those kinds of things. It's like teaches the computer what it can call, but does not necessarily always give the developer like a fun, light bulb experience of sending a, an SMS with Twilio or sending an email with SendGrid or whatever those things are. It's like it should be fun. And I, you know, I, I've always thought of APIs. Turning on a light bulb across the world, right, is it's just fun to have that as a superpower. And now we can charge a customer and stripe or, you know, send an activity to segment and have it populate everywhere we need it.

CJ: So I was curious and I, I jumped in, I did write a couple of orbit integrations, like one for piping in some dev.to blog post activity, and another one for piping in YouTube. and I was looking at like, oh, did I just hit the a p I directly or did I use the S D K? And in one of them I used the, the Orbit s d K, the other one I didn't So yeah, I'm using Orbit activities request and then passing in just like a giant blob of arguments and the body and everything.

Colin: Mm-hmm.

CJ: And then in the other one, I'm using REST client to just hit, uh, like orbit.love/api v1 or whatever.

Colin: Nice. Yeah. I mean, it's something that we all have to make decisions when we, we actually have our own Orbi HTTP client now, in Ruby and. I think it'll be interesting. I'll have to see if. Coworker Steve has any interest in eventually opening that up. But it has a lot of that rate limiting stuff built into it like we had with Discord. We sometimes will use official SDKs for our integrations, but sometimes, like if our API is only going to ingest data and never create data, some APIs don't give you API keys that are read only, things like that. So like we're like, we only. The endpoints that get the data. We do not want to even have a method that lets us delete or create or any of those things. Um, but also just sometimes like, just being able to standardize, re responses, standardize what happens after, cuz every sdk like we're talking about here, the experience, the opinions of the developer team that put together the sdk. So like, Because of how we built out our newer integrations. They almost all use that Orbit HTTP client, which I think is a wrapper around rest client. But there's just like a bunch of really nice helpers and it's more declarative. So you can just say these are the end points and we're not rewriting. Cause that's like the challenge when you do a lot of integrations is that you're doing the same thing. And translating it to every API , and being able to have some standards once the response comes back, we know what it looks like every single time, which is really nice,

CJ: So this is the client that you're using to integrate against other third parties, not against the orbit? Right. Okay. And then are, gosh, I, I almost wonder if it's possible to like, Take the third parties and see like, oh, do all of them have open API specs or something like that, that you could then use to build that? Like, yeah, the, so like you have your H C D B client, and then you could build like that middle layer that we've talked so much about, which is like the adapter layer. And I, it sounded like you had a pretty cool, uh, like pipeline

Colin: Mm-hmm.

CJ: Right. But.

Colin: yeah. Each integration essentially ends up with its own like Stripe client for example, that uses the Orbit HTTP client. And it's just the methods we need and because everything is built on that client, we don't have to go implement everything all over again. It's just really like, is to get, what's the endpoint slash customers or whatever. Obviously once you release something as like a public gem or whatever, now you comes with a burden of supporting it and documenting it and taking issues and prs and all that kind of stuff. So do you, you guys, I'm assuming, don't take PRS necessarily against these SDKs then, right?

CJ: So there are parts of them that are not generated, and we will take prs on that. It's kind of like, I, I refer to that as like the core. So if it's, if it is that sort of, um, item potency or retries layer or interacting with, you know, SSL or, um, the patterns, like, oh, is this a client? Versus client services or class method or whatever. We will take PRS to modify that core. But all of the pieces that are boiler plate, that mirror the api, those are all generated and it wouldn't make sense for anyone to make a PR

Colin: But they can record an issue so you guys can go check it out and see like, oh yeah, that's actually not correct,

CJ: Exactly. And I would love to see us actually move the generation code into the, into the open source. Libraries. The generation code right now is all private sourced. And I was looking at, AW s gem, I think this might be the most popular Ruby gem by downloads or something like that. Uh, and they also generate this client. But they're doing it in a generator that's open source and it's like part of the library. And it was interesting to look at. They have basically these giant mustache templates and then they iterate over some input, some input that's like similar to open API spec. They don't have this intermediate stripe type. Style compiler thing. But, uh, I do love to see the generator there because as an open source contributor, you could make a change to the generator that's like, oh, it would be better if it was like this, or it'd be more perf like performant if we use, I don't know, yield instead of block.call. You know, I don't know, like the actual, you know, Ruby, whatever, magic stuff, but.

Colin: And someone might learn from this, uh, you know, AW S one and start generating their own SDKs for their own. Like, we, we would just end up with better SDKs all around. Right? It's like putting it out there so that more people do this as a, as a, as a norm. Instead of it being like, you do what

CJ: Yeah. , it's super hard to explain all of the benefits of Prettier poet in like the way that it looks and feels and the shape of it. So, . I'm hopeful that, uh, if this is interesting to you or you're inspired, you go, he head over and like check out the talk on YouTube,

Colin: Nice

CJ: there will be like code examples and such.

Colin: is Prettier poet open.

CJ: Prettier poet is not open and that's another thing that I'm like hopeful that we will eventually open source.

Colin: Yeah. So you're you're here in Nevada. Here first, you know, or if you're at Ruby Comp, you'll, you'll get to hear some of this as well. That's, uh, Ruby Comp is the one that's in Texas. Is that

CJ: Yes. I'm gonna go to the, yeah, Ruby Comp Texas, because the Ruby Comp Mini, that was just in Rhode Island right down the street, was gonna be the same time as the develop like chirp developer conference that we just missed. So

Colin: Thanks Elon. Thanks Elon. Awesome. Well, I think we're at time for today, so it's awesome to kind of dive into SDKs and all the stuff you guys are doing at Stripe. I'm definitely gonna go take a, take a peek at our SDKs after this and think about what we might need to do. you said you wrote them for seven years, were not. At that point, like we're probably gonna be handwriting ours for a while, but at least getting some eyes on our s STKs and just thinking about how we're doing that would be, would be good.

CJ: totally. The show notes for this episode are available@buildandlearn.dev. That wraps it for this episode. Thanks everyone.

Colin: See ya.