go podcast()

I receive Chris Shepherd and we talk about gRPC in Go. If you're building systems with lots of micro-services, gRPC is a good way to provide strong contracts between your services and improve communications.

Links:

The best way to support this show, other than talking about it, is by purchasing my online courses on Go: Build SaaS apps in Go and Build a Google Analytics in Go. Here's a direct link with a special discount for the pod listeners.

Creators & Guests

Host
Dominic St-Pierre
Go system builder - entrepreneur. I've been writing software systems since 2001. I love SaaS, building since 2008.
Guest
Chris Shepherd
Senior Systems Engineer @Cloudflare

What is go podcast()?

15 minutes news, tips, and tricks on the Go programming language.

Dominic:

Hello there. I'm Dominic Senthien Pierre, and you're listening to Go Podcast. Today, I'm receiving Chris Shepherd and we are talking about gRPC in Go. Hello, Gophers. So before we dive in with my conversation with Chris, I'd like to, to remind everyone that, well, if you want to, to show your support for the show, if you appreciate, what I'm doing, the best way to do that is by buying my courses.

Dominic:

So I have a direct link in the show notes. So, I mean, I'm I'm doing everything myself. I'm not getting paid for this podcast. I do all the editing and everything like that. So, I mean, if you want to chip in, that would be appreciated.

Dominic:

And on that, this is my conversation with Chris. Hey, Chris Sheffer. Thank you very much for accepting this invitation.

Chris:

No worries. Yeah. Thanks.

Dominic:

Right. So let's start very quick. So I I like to, ask my first question is something like, you know, can you introduce yourself? But, you know, let's let's have a small, bias towards Go. So, you know, describe yourself, what you what you are doing and things like that.

Dominic:

But, you know, if you if you can give a little bit background, on your Go experience, that that would be very nice.

Chris:

Yeah. Sure. Yeah. So, actually, I'm Chris Shepherd. I'm a systems engineer based in London, currently working at Cloudflare.

Chris:

So at Cloudflare, I primarily work on our audit logs products, which kind of acts as a system of record for customers to see any changes made on their account. And as part of that, we provide, like, an internal platform to other product teams at Cloudflare as well as providing functionality for customers to retrieve and view their audio logs. So I've been working at with Go for about 6 years now. I actually started my career mainly using Java, but at the time, I wanted to kind of I was very keen to explore other things and try other languages. And then once I came across Go, I just just really loved the the simplicity of it, to be honest.

Chris:

I like how it works without any kind of magic going on, which which is kind of a far cry from things like Spring Boot and Java. So, like, the with those sort of framework here, they they work really well when they work. But as soon as there's an issue, you end up spending all your day searching Stack Overflow for some very confusing stack duration. It's really hard to see what happens, whereas in Go, you don't really have that problem.

Dominic:

Yeah.

Chris:

Because it's very easy to see exactly what the code is doing all the time.

Dominic:

Yeah. That that is so true. I mean, this I'm coming from a dotnet, background, and I it's crazy the amount of time I was I was, you know, having to pass on Stack Overflow back then. And I don't know if it's because I was a, you know, more junior slash intermediate at this time. I I I'm not sure but I I think it's really tied to the platform because there's so many things that that is related to those, Gigant desk, frameworks and and just the standard library in in Java and dot net.

Dominic:

It's it's crazy the amount of things that you need to know.

Chris:

Yeah. It's true. Yeah. Whereas with Go, like, I think it certainly feels a lot more modular. Like, you kind of pick things up as you go.

Chris:

And if you do come across issues, it's very easy to like, you can even step through the source code, and you can see how things work. And it just yeah. It feels much easier. It doesn't, like like you said, I don't I don't know whether it's because I was more junior at the time, but I don't find myself going on Stack Overflow anywhere near as much as I used to. You know?

Dominic:

Yeah. I think we should we should, maybe re re return to to do some, Java and dot net to see if, if we were if we would would go as a minority. That that's that's not where it is. But, you know, joke aside, so today we will talk about, well, gRPC, in fact, a little bit. Well, not a little bit.

Dominic:

It will it will be the the the most the the main topic of this episode. So let's start by, you know, the the obvious question. You know, what what is gRPC in your in your words? And and if someone was sleeping under the rock for the last, I don't know, 5, 6 years, what are they missing?

Chris:

Yes. So gRPC is a it's a modern open source framework, RPC framework written by Google. It uses HTTP 2 for transport and protocol buffers for interface definition language. And the the main idea around it is it's language agnostic. So it makes it really easy to build Polyglot services to communicate with one another, which makes it really ideal for kind of architectures where you have a lot of microservices to, like, talking to each other.

Chris:

And because it's built on HTTP 2, it it has a lot of benefits over, like, regular like, other frameworks, like REST, for example, just because it has a lot of kind of performance improvements and with things like multiplexing and also, because it uses protocol buffer, it's an it serializes data in binary format, which means messages are much smaller, so there's a lot of high performance features as well.

Dominic:

Yeah. Totally. What what would be what would be your guide to you know, if someone is agonizing, you know, if if they should use gRPC over REST API. Let's say let's say someone is is very used to build, you know, standard, JSON API like we are building for, for a long time now. But what what if, you know, what would be a good rule of thumb you think to decide if gRPC is a good choice or if they, if they might, if they might continue to use rest, do, do you have a, do you have a guideline for that?

Chris:

Yeah. I think for me, like, for kind of service to service communication within microservice architectures, I at least for synchronous communication, I would typically use gRPC. That's mainly due to its strong message structure. It's like it's useful in architectures where you have a lot of various lightweight services communicating frequently. Because these contracts are kind of defined up front using Probuph, it makes communication type safe.

Chris:

And so it reduces any possibility of kinda mismatches or errors, which, obviously, you can build clients and you can kind of provide that functionality yourself with REST, but, like, this is kind of baked in out of the box with gRPC. And also because it's language agnostic, like, if you have a lot of different microservices in a lot of different languages, it really fits in. Well, that means you're not writing a lot of you know, manually writing a lot of this code yourself. It's funny, like, I actually have a very good story of kind of a a situation where I wish we were using Jira PC in the past. So it was actually a few years ago at a previous company I worked at, and, the company I worked for at the time provided a digital wallet.

Chris:

So you can kinda think of it similar to Apple Pay or Google Pay. And at the time, we had it was my first experience writing Go, first building microservices. I was only at the company for a few weeks, which made it a little more scary. And we had a lot of we had a lot of microservices communicating with one another, and they were using REST. And at the time, we were kind of we were manually creating these REST clients to and then, like, importing them into other services.

Chris:

So at the time, I was looking at it. It was a very simple ticket just to change a time a type from a string to a timestamp. So I made all the changes, got it all approved, run it through our automation test framework, and all looked good. So I naively, at this point, assumed everything was fine. I deployed the change, moved on.

Chris:

And then next minute, we got a lot of reports from customer support saying that users' cards seem to have been deleted from within the app. And that's when I realized that there was actually another microservice in between the one I'd worked on and the app. And it was it was making a REST call. I hadn't updated the the the contract the the the client. Sorry.

Chris:

And, and I I just realized I'd introduced a breaking change into one of the APIs. And because of this, it was actually marking every user's card as deleted. So that was every single user, every single card for every single user. Ouch. So, basically, at the time, if anyone had gone into the app, they would have thought their account had been wiped.

Chris:

So that was a that was a very, very, yeah, stressful time, let's say. But, yeah, I I always think now, like, if we were using gRPC at at that moment, like, I I could have still done that change, and I could have still, you know, obviously, broken like, we could have broken that contract there. But at least with protobuf, like, when you're making that change, like, you have to give it a bit more thought. And, hopefully, at that point, I would've realized what I was doing. But,

Dominic:

you know Totally. So so, yeah, that that that was that was one thing I we I I wanted to to touch base a little bit about about breaking change, but I think you just you just probably nail nail exactly what, you know, what what's the benefits of of protobuf. Because I mean, in that that particular situation, the the the service in the middle would would have, you know, break. And and now at least the the data would, would have been, maybe saved a little bit or at least not not flagged as as deleted like like you described.

Chris:

Yeah. Yeah. Exactly. Yeah. It would have like, we would have picked it up earlier because we would have seen a bunch of errors in the survey, like, in that integration in between the two services instead of the request was being were successful.

Chris:

It's just the yeah, it was just the way it was unmarshaling the the JSON response in the the upstream service. Yeah. It was just

Dominic:

Yeah. Yeah. It

Chris:

was kind of failing silently.

Dominic:

Oh, yeah. That's the that's always the worst. I mean Yeah. Silent fail. But, you know, while we are on this breaking change, you know, thread and whatnot, I mean, how did you how did you end up with that?

Dominic:

Because this thing still still happens in gRPC. Are how are you handling putting something in production that you know will break other, other services? So what what is your typical, you know, workflow and whatnot? Are you are you, like, contacting, other teams and saying, well, you know, this this contract will will change now. This this a this API is now is now, I don't know, returning something else, a different type, or accepting something something new in in in the call of a of a function.

Dominic:

How are you handling breaking change?

Chris:

So typically breaking change should just be avoided at all costs. Like, there are obviously some kind of situations where they either can't be avoided or if a con if a prob if a geography service is not being used, then maybe breaking change is okay. But but, generally, we have a rule, at least at Cloudflare, that, like, wherever possible, we should just not make breaking changes at all. And kind of to enforce that, we actually have built, like, a ProtopoF registry that we use across all of our Geopacy servers. So we have, like, a centralized repository that contains all the ProtopoF code, and in there, we have a lot of build tooling to kind of do different things like linting the protobuf and, checking for breaking changes before then generating the code and publishing packages for various languages.

Chris:

So one thing we do in there is we we check that any changes don't con any, like, schema changes don't contain breaking changes. And, we do that by using a tool called BUFF, and that that has, like, a that has a it's a BUFF is, like, a toolchain for protobuf, and it has a you can run the CLI command to check if breaking changes. And if it will check things like if RPCs have been deleted or if, data types have been changed, things like that. And if, it will it will flag an error if that has happened. And the really nice thing about buffer is you can run it as part of your CI pipeline.

Chris:

So we, at Fireflies, we do that when when you make a change and you you push the code and you create a PR, it will run these changes in CI. And if there are breaking changes in your code, it will actually fail the build. So we can block that. We can block that PR from getting merged at that point. So it makes it really it makes it almost impossible to actually deploy these breaking changes.

Chris:

Or not deploy, but like

Dominic:

Yeah. I like I like that a lot. So the this this tool, so it's not it's not an internal tool that you build at Cloudflare. Right? The the buff, CLI?

Dominic:

It's it's

Chris:

No. No. Buff CLI is a is a publicly available tool.

Dominic:

Oh, that's interesting. So the fact that you have a centralized repository for your proto file,

Chris:

publish that our probosc won't get published all those changes unless there's no breaking changes.

Dominic:

Yeah. I like that a lot. Do you do you know do you do you know if it's, if it's a common practice, in in bigger software companies that those those protobuf, so those protobuf would would be, you know, would be centralized like that?

Chris:

Least in my experience, like, at the I've I've worked at 2 companies now where we've used Geofsy, and in both companies, we've had a kind of similar registry like this. I don't know if it's common practice, but I I think it should be. I think Yeah. Probuff can be very difficult to work with at scale, and I think, like, that's probably one benefit to using something like REST. We don't really have to think about these things.

Chris:

But, but, like, I at my previous company, I was there when we first adopted gRPC. And at the start, we did I kinda didn't give this a lot of thought, and it became really, really came challenging to manage after we started building a few different services. And we'd have bits of protobuf file in kind of different repos next to the service, and we'd be generating them just using, like, ad hoc protoc commands and generating the code using ad hoc protoc commands. And you kind of end up with protobuf in different versions. You'd end up not really knowing what APIs we have where, and it would just, like, it just became kinda difficult to manage.

Chris:

Whereas, like, if you have all that all those schemas in one location and you're generating it with, like, standardized tooling, like, at least, you know, you have much more repeatable builds, and it kind of acts as a form of documentation. Like, it's very easy to discover what APIs you have if they're all listed in one central location.

Dominic:

Oh, yeah. Totally. So so so you're you're saying that before having it, in in a central repository, you you were having some kind of distributed file all all over the place, basically. Right?

Chris:

Yeah. Yeah. Yeah. Exactly. Yeah.

Chris:

Like, we used to have like, it would be very I think at the time, because we were we had a lot of microservices not using gRPC, it was very difficult to know which services were gRPC and which ones weren't. And if you didn't know the exact name of the service, it was really challenging to go and try and find it and see exactly what kind of what APIs it provides.

Dominic:

And you you mentioned something interesting that, that kind of made me made me wonder. So you you say that it's it's difficult to scale, gRPC. So can you can you yeah. I mean, extract that a little bit? Elaborate?

Dominic:

What's what's your what's your meaning by that?

Chris:

So I mainly meant, like, around, like, scaling the usage of Processed Off more than more than scaling, like, the service itself.

Dominic:

Right. Right. Right. Right.

Chris:

But, I I think this is something that, at least when I first joined Cloudflare, we we struggled as well a little bit, is that, like, at Cloudflare, we use many different languages. I think we have about 7 different languages that we use typically. Like, Go is our primary language, but we have a lot of teams writing other things. And it was kind of the same there. Like, when I first joined, we didn't have this kind of standardized registry for our geography protocol.

Chris:

And we would have, like, one team writing Go, and they would have a pro a geography service which generate would generate a code in Go. We might have another team that's writing Rust, and they might want to use that Go service, but there's no Rust. The the code's not been generated. Like, there's no probab client in Rust because the the first team just didn't think about generating it. Yeah.

Chris:

And then, like, the problem I said about discovery with APIs, like, that as your company grows, like, that gets even more difficult. So, like, that, like, that was the biggest thing for us at Cloudflare is once we moved to this kind of centralized repository, it meant, like, out of the box, when someone creates a geography service, they automatically get their code generated in 7 different languages besides just the one that they use every day. And it means that other like, engineers are not searching through different repos, searching through Wikidots, things like that to try and find what service they're looking for.

Dominic:

That, they yeah. Totally. I I can see I can see how how it could streamline the the development process. This is interesting. 7 language at Cloudflare.

Dominic:

Wow. This is, this is impressive. I I did not knew that. Do do do do you have any, exotic language in those? You know, any any Haskell or any, any any of this, you know, strange stranger language that that we, we don't hear about too much?

Dominic:

Or it's it's basically just the the good old good old, you know, Java and and things like that?

Chris:

So I at Cloudflare, we kind of we're not very prescriptive on what how teams work really. So I think, like, if teams wanted to use specific languages and they kind of have a good use case for it, then they're welcome to do so. So I'm sure we do have some kind of exotic languages like you said, but I can't think of any examples off the top of my head, to be honest. But I I think the primary languages we use are Go. I would say we use Go for the vast majority of our thing of our, services.

Chris:

But then we also have, like, an awful lot of Rust as well. And then we use quite a lot of, like, NPM so a lot of nodes and TypeScript, that sort of stuff.

Dominic:

Right. The, inevitable, I would say.

Chris:

Yeah.

Dominic:

Yeah. And and what about what about clients for, for those, JavaScript, you know, JavaScript client in in, gRPC? Is is there do do you have any anything to say about that? Is it is it is it, like, smooth? Because, I think I think you need a plug in or something like that to generate some kind of, client side JavaScript?

Chris:

So, yeah. So I think when you generate the code using protoc, like, for each language you generate for, you kind of need their own language specific plugins. I think for for for, like, the Node ecosystem in general or the NPM ecosystem in general, There's 2 types. There's a kind of, like, the node bindings, and then there's the gRPC web bindings as well, and that's more for, like, client side JavaScript. Truthfully, at Clavla, we don't use gRPC externally.

Chris:

We kind of only use it for our internal service server communication, so we don't actually use Geoffc web, but, but we do use it kind of on the back end. But that's like another thing another advantage that we get from our, centralized repository that basically, like, we like, one thing that I've seen problems I've seen in the past is that whenever an engineer wants to generate code in multiple languages, they kind of have to have all these protoc plugins installed on their machine. So, like, like, in like, if you think you've got if you've got a lot of languages out there, like, you might need a Python plugin that's installed via pip. You might need a Node plugin installed by npm, like the Rust one by cargo to go on and install from go install. And that gets pretty challenging, like, if especially if you're an engineer who's not really familiar with the other ecosystems, like, it gets kind of challenging and probably gets quite frustrating to have to install all those things if you don't have them already.

Chris:

But that's one nice thing we get with Buff, is Buff has its own schema registry, which kind of acts as like a proto a package manager for protobuf. And with Buff, you can kind of define this list of plugins in a config file. And then you can just run, like, the buff generate command, and that will pull those plugins from the schema registry and generate the code in every language that you need out of the box. So it makes it super, super simple to do that.

Dominic:

I like that a lot. I I must admit, while this, this seems to be, this seems to be very clean the way, the way that that it it is handled. Have you have you seen any any issues with the code generation, you know, the the code that is generated by, by by protoc? I mean, did you do you have any any kind of story? Because, you know, I mean, cut generation, is still is still you know, sometimes it's not it's not the best one.

Dominic:

So do you have, do you have any issues? Or or, I mean, it's it's all, it's all good and well from your side.

Chris:

Frankly, I haven't seen any major issues with the generated code. I have to say, I think Geoxie support for Go is much stronger than it is for a lot of the other languages. I think partially because it was written by Google, probably primarily for Go. So I think it can be challenging to find the right plug ins for certain languages. I this is something I've experienced with TypeScript in the past where, like, there's a lot of different kind of third party plugins, not not official ones, for generating the code and that, like, with JavaScript and TypeScript in general, there's always a lot of different ways to do something.

Chris:

So I found it a challenge before making sure you find the right kind of plugins for the project you're working on to make sure you generate the codes in the right way, or, like, making sure you provide the right kind of advice on how to how to use the product that's generated. But, yeah, besides that, I can't think of any specific issues I've seen with the generated code itself.

Dominic:

Yeah. Yeah. That's that's a good news then. I mean, it's it's, you know, if it's Cloudflare, I I don't know, compliant. If we we can say that, it it should be it should be fine for a lot of, a lot of us, I would say.

Dominic:

So do you know, what what about, what about HTTP 2? I I know we we we've talked a little bit about that, but I mean, can you I don't know. Can can you tell us a little bit about if you ever use the maybe maybe the bidirectional, way of of communicating. So let's say you have a client. Let's say you have a client that that talks to a service or or 2 or multiple services that, I don't know, need to be in in kind of real time communication?

Dominic:

Do you, do you use that a little bit at, at Cloudflare?

Chris:

To be honest, at Cloudflare, we don't typically use it a lot. I think that's largely just due to the architecture that we have. And at Cloudflare, we we have a an event based architecture, which is backed by Kafka mainly. So any kind of event streaming type workloads go, handled by that. But I think I I can definitely see the the value of it as I got at the same time.

Chris:

One one use case I did use at a previous company was just as a replacement for Polling. Essentially, we had, we had an API that basically made a request to initiate a process that was kind of kicked off a bunch of downstream processing. So instead of the mobile app polling our API, we used server streaming to stream updates until the process was successful. Now that worked pretty well, but I have to say, I it was probably overkill for our use case. I think polling would have been more simpler, and we wouldn't have had to worry about the kind of the failure mode so much, like, if the connection drops and things like that.

Chris:

But at the same time, I can see how the, like, HTTP 2 features are kind of really useful for situations where real time communicate communication is key. Like, good examples of this would be, like, gaming servers or financial tickers. Because you can, like because these connections are long lived and you, like, can stream data directly to the client, I think. And also because it's binary encoded, so the payloads are typically much smaller than kinda text based formats like JSON. Like, the performance is just much quicker than you'll get with something compressed.

Dominic:

Yeah. Totally. Totally. So, so yeah. So you so you would get you would you would say something like, you know, it depends and could be interesting, but but you you recognize that the complexity, it it adds a little bit complexity, I I would say, may probably.

Chris:

Yeah. Definitely. I think, like, I think polling is always gonna be simpler just because

Dominic:

Yeah.

Chris:

If you if you're polling an endpoint on its sales, you know you're gonna call it again next like, in the next time. Whereas with this, like, if the connection drops, you kind of have to handle that retry logic and things like that and handle error scenarios that you just wouldn't get otherwise.

Dominic:

Yeah. Totally. What what about I mean, okay. It's it's all good. It's all good.

Dominic:

We've built some, services that use gRPC. We have some clients. What about, I mean, the famous authorization and, authorization and whatnot? I mean, what what are you what are you using, internally? So because you're saying that you you're mainly using the the services, internally.

Dominic:

So I'm I'm curious to, to see a little bit about the authentication.

Chris:

Yeah. So I think we've handled this in a few different ways, because it because we have, like, our services are primarily running inside the Kubernetes cluster, and they're not exposed to the outside world at all. We're kind of quite safe in that we know that the traffic is going to be coming from an internal service. So in some cases, like, in some cases, we we can just handle we don't have to worry so much about SSL or TLS, things like that. We can just kind of handle plain text communication, and that's fine.

Chris:

However, we have some services where we require the data to be sent encrypted in transit. So in those cases, we we use, mutual TLS for that. Mhmm. Which it has good support for. So in that case, you you provide a certain key from the server side, and you provide one from the client, and they both validate verify validate each other to make sure that, you know, we we only allow certain clients to talk to our services.

Chris:

But, also, we can restrict that. At least inside the Kubernetes cluster, we can we can restrict which clients can talk which services can talk to our JOB C servers using network policies as well to just ensure that we're happy that only certain clients can communicate. But in terms of authorization as well, like, I've seen, like, different approaches to this as well. So, like, some services, we're kind of happy to not have any additional authorization logic. Like, we're happy if that connection can be made, then, you know, we we don't need to validate, like, the a token or anything like that.

Chris:

However, like, if a service is exposed publicly, like, hypothetically, or if we do want more granular author authorization on our service, like, it obviously does support middleware. So, which is kind of similar to HTTP headers. It allows you to, like, kind of pass custom sorry. It does support metadata, not middleware, which kind of acts as HTTP headers. And it also but it does also support middleware, so you can basically create custom logic that runs on each request before it before it hits the main Jira C service, but, like, the server code.

Chris:

So in that place in that case, it's kind of possible to send a token in the middle where in the header, and then in the middle where we can kind of pass that and extract the claims and make sure that the token is authorized to do the operation.

Dominic:

Nice. Nice. Yeah. Okay. That, that makes sense.

Dominic:

So let me, let me throw at you a small, a small, you know, real world situation. I, I have built a an open source, you know, a group project. It's basically a back end server API, that is kind of similar to in a, you know, in a very, very lightweight way to to what Firebase is. So basically, it's it's like a an easy database, user management, you know, file storage and whatnot. I mean, basic build building blocks that most, web application need.

Dominic:

And I built that with, you know, with the rest, approach, if you will. My question is how would you approach maybe not rewriting, but I mean just transitioning from a REST API to a more gRPC approach. Is it is it even a good idea to do that? Is it have you seen, I don't know. Have you have you seen services that do handle both in in in a certain transition?

Dominic:

I don't know what you know. Did did have you, have you had to to migrate such a such a service?

Chris:

Yeah. I have done this in the past. I triply, I would say unless there's a specific need, like, unless the service is causing problems or if we you feel the need either or you feel the need to have, like, kind of take type very strong schema and type safe communication, or maybe you need to take advantage of the HTTP 2, functionality. I think if it's not for those reasons, I generally, I probably wouldn't migrate. I think, like, REST is perfectly acceptable, and, like, I I think I think it would be fine to leave as it is, but, but, yeah, like, I I have seen this done, like, these migrations done.

Chris:

And, like, there's kind of 2 approaches I would take to this. I would one is I would I I would, like, I would create the the product and the definition, the service, and and all that. And then, like, when it comes to actually doing the migration, you could kinda you could either kinda spin up the Jira proxy service inside the same, deployable, inside the same executable by running it in a separate guarantee and listening on a separate port. And I think I think that would work fine. That's that's how my previous company did it.

Chris:

We kind of just, if we want it to run both in parallel, like, we actually have example services where we might want it to expose this, an REST API directly to the mobile app. So we'd create a HTTP server on port 8080. But then also we might need one like a GRPC, internal server to communicate with our other services, and then we'd open a port on 50051, which is the the standard port for gRPC. So in those cases, we kind of have both service servers running on separate go routines inside the same deployable. But if you wanted to kind of separate them a bit more and just make sure that they can both scale independently without causing without causing problems for one another, then you could easily just, create kind of a separate main file and separate deployable for the gRPC server instead of running it in the same thing.

Dominic:

In the same program. Yeah. Yeah. I I I I like that, idea a lot. So so, yeah, I I you know, there there it it's not it's not really something that I want to do.

Dominic:

It's some something that opened an issue, and I was like, that's interesting. I mean, I I I never really thought about building the gRPC way for this type of application, but now, you know, the issue is created and now you you you start to think, well, maybe maybe there's something there. But I mean, I'm with you as well. If if a system is working, I mean, there's there's not much in but it's you know, I mean, it's not it's not something in production. It's not it's not even something that that is running, anywhere, meaningful, I would I would I would guess.

Chris:

Yeah. And one thing I would say is, like, if this is an API that customers are directly communicating with, I would and it it like, a public public API and not one that's just being called from, like, a system another client that you're running yourself, then I I typically wouldn't use gRPC. I wouldn't do a migration for something like that just because I think REST is generally easier to communicate with.

Dominic:

Yeah. Yeah. I hear you. So so, basically, what what's what's your saying is is is it like so gRPC is really good for internal communication of of your services. But as soon as as you go, you know, in in a public API, you know, RISC could probably still be the the the best choice here?

Chris:

Yeah. I think so. I think, like, although I don't think it's a a large learning curve, I think there is a learning curve with gRPC that you don't typically have when writing, like, HTTP APIs. I think, like, obviously, like, every like, customers would have to be familiar with protibuff and how kind of how that works and creating clients and all that stuff. Whereas with REST, you can kind of just do a curl command and get a response.

Chris:

And, yeah, I think, typically, a lot more people are just familiar with with rest in general. So it's, yeah, it's much easier to push adoption, especially to customers with things like that.

Dominic:

Right. Yeah. Yeah. Totally. Totally.

Dominic:

So that's, yeah. That that's very interesting. So do you I mean, do do you have any any kind of, I don't know, horror horror story or downside of something that you've seen that, you know, gRPC, really, I don't know, did not really made sense or that it it, you know, it make you, or, you know, make makes the team a little bit more less productive or things like that. I mean, is it is it always smooth?

Chris:

I would say I would say some of the tooling around Gopcsie is kind of a little bit immature. And I think for that reason, it kind of does make it a little challenging to work locally with and, interact locally with. I although I think it has got a lot better over the past couple of years, but, like, I think it it can be challenging from that aspect. Like, for example, things like Postman, they've kind of only recently started for gRPC. So I think, like, debugging and interacting with an API is just not quite as easy with Job c as other frameworks.

Chris:

Like, I remember when we first started using it at my previous company, like, we kinda just didn't have any good way to interact and test things, which was not ideal. Like, and, like, we'd have little kind of scripts that people would write and, like, little commands just to kind of, like, just to just to hit an endpoint, which is which is not ideal. And the other thing is, like, with geography, you kind of, like, you need to provide the profiles to actually do that testing and actually, like, hit an API. Either that or you could use server reflection which probably don't want, which server reflection is a way to kind of expose information about the APIs that are available on the server externally, and that's probably not something you'd want to

Dominic:

Yeah.

Chris:

Probably, like, you have enabled on a production server. So, like, yeah, I I think the tooling has gotten much better, but I think that's kind of the pain points I've seen at least with JOB C in the past.

Dominic:

Yeah. What what you just said reminds me a little bit of, those old, you know, SOAP services back then, the XML, SOAP services. I don't know if you if you had some, some experience with that. But, yes, there there there was, like, this, this public portal and and people could, you know, it was acting like a documentation as well. I mean, in in a sense, gRPC is a little bit like that, but it's just I mean, it's it's it's just, you know, better, better design, I would say.

Dominic:

Because, I mean, soap was was kind of extremely verbose. But, I mean, at the end of the day, an RPC is an RPC. Right? Yeah.

Chris:

Yeah. That's true. Yeah. I think, yeah, like, the biggest difference is just that so it's XML. JLC is pro above.

Dominic:

Yeah. Interesting. I mean, do you do you have any, any closing thought, about, gRPC? I mean, do you have, you know, I don't know, resources that that you want to, to talk about before we, we close this, this episode?

Chris:

So I think, yeah, for anyone who is using gRPC at their company or looking to adopt it, I certainly would look at, like, obviously, you'd want to you want to build fast and, you know, not not build a lot of, like, pre optimized. But, but I think it is definitely worth giving some thought to how protobuf is managed and, not just rushing in and building things because it can be very hard to go back and undo those things. Like, if you if you have forever all over the diff all over the place, it can be very difficult to then go back and migrate that to an essentialized repository. So I would definitely, like, recommend thinking about building something like that to start out with. Like, it maybe doesn't need all the tooling around it, but, like, potentially, we have a clevla, but, like, you know, just having somewhere with all the product in one place, I think definitely makes sense.

Chris:

It's something I actually have created, like, a sample repository for this, in the past just for, different project I was working on, so I can I can share a link to that as well? But I would also, like, encourage people to check out Buff. I think it definitely makes working with Probuff a lot easier as well, Like, just generating code in different languages and having to deal with the proxy command is not always the easiest, especially if you're very new to very new to this stuff. So I would definitely recommend checking out Buff because it it definitely makes things a lot easier.

Dominic:

Yeah. That makes a lot of sense. Yeah. We will, we will have this link, on the show show note for sure. Maybe maybe just one last question, about about those breaking change.

Dominic:

Do you're you're saying that you you try to not introduce any breaking change, but does does that does that cause you having a lot of versioning here and there all over the place? You know, if something needs to change, I mean, the only way is is probably to create a new, I don't know, a new function for that or at at least a new, maybe not a new endpoint, but either a new version for that thing or, rename that for some services. And now you have, you know, I don't know, a group of services that is using, function a and and another one that is using function b. Is is that, is that the situation?

Chris:

So it's not typically a problem we've it's not typically a problem we face a lot. But, yeah, like, that definitely can happen. I think if, like, just changing a field name, it's quite simple, or changing a field type is quite simple. You you can mark the old field as deprecated. So we do definitely have some kind of prep of contracts where we have a lot of deprecated fields, and it it looks kind of messy.

Chris:

But, but I think it I think it makes sense to avoid, avoid making that breaking change because if you do that, then you suddenly have to start kind of coordinating releases to make sure that you're deploying clients and servers at the same time, and then it that still makes it impossible to make sure you don't catch any don't, end up with any errors at all. But at the same time, like, I would it's worth noting that, like, breaking changes are not, like, strictly forbidden. Like, we we do have we do make exceptions to these to allow certain changes to to be merged if in, like, in some circumstances. Like, for example, if we know, like, that product contract is not being used or if it's we know it's not gonna cause a problem, like, by making that breaking change, like, we will we will merge that and make the change. Obviously, it's not, like, strict best practice, but I think, like, it's best to be pragmatic in these cases, and it's better to keep the protobuf as tidy as possible in cases where, like, really the breaking change won't make that much difference.

Dominic:

Yeah. Yeah. Totally. I hear you on that. That's that's that's very interesting.

Dominic:

I mean, it's, it's the second, guest that we have, on Cloudflare. And, I mean, I'm I'm learning a little bit more and more, and this this company seems to be very interesting to me. Cool. Cool. That was, that was great.

Dominic:

I mean, let's, let's close the show. I tried to have a one question. The last question that I'm I'm, asking guests. Are you missing anything in Go? Is there anything that you are missing from, I don't know, maybe Java?

Dominic:

You were you were talking about Java at first. Maybe it's that. You know, is is there is there anything that you you would like, you know, to have in Go that that that is not present at the moment?

Chris:

Yeah. As much as I would like to say now, I think Go is perfect. There's definitely nothing. But no. I think it's funny.

Chris:

Like, I actually I'm still like, the more I let go, the more I realize how great it is as a language. But I do, a lot of times, miss a lot of, like, a lot of features that you get from languages like Java because, like, they're not I think Go tries to be as simple as possible and as idiomatically as possible, and I think that's a really great thing. And that, that's has definitely really helped me in the past keeping code bases clean and as they as they grow. But, but there are times where you think, like, just things like the Lambda functions in Java and, like, the the, like, the functional API. Like, I think it would be I I really like that in Java, and I think it it it can be really powerful.

Chris:

I think one thing that I one feature I really like, it's kinda syntactic syntactical sugar. But, one thing I really like in Kotlin is the extension functions. So that's kind of a way of extending existing classes with new functionality with inheritance. So, essentially, you can define a function on a preexisting type, and it it it acts like it was originally a part of the original API. So I I kinda like that because it it makes it very easy to make code easy to read and maintain, and you really have to add methods that are specific to your needs, and it looks like it's a part of the original code.

Chris:

So try to think of a good example of something like this. Like, let's say you have a a string that's a password. You could add a a function to the string data type that would say is password, and it would kind of validate that it's a password, something like that. Like, it's kinda syntactical sugar because you could just create that function and pass a string into it. But, yeah, yeah, I think I think it's quite a nice function, the functionality they have in Kotlin.

Dominic:

Yeah. Sure. I I I think if you if you were to alias the string, type in Go, you could you could create a a function that received this this type and now but but I I hear you. It would would not be attached to the, you know, the primitive string, of Go for sure.

Chris:

Yeah. Yeah. I definitely I have thought about doing that before because it's kinda similar, but I don't know. I don't like the idea of having to do kind of necessary casting and things like that.

Dominic:

Right. Yeah. Sure. Yeah. I I must admit that.

Dominic:

Yeah. I I also miss sometime the Lambda in, in in C Sharp as well, which is probably probably similar to to Java's. But for for me, it's it's really I keep saying that in this podcast. But yeah, I will I will continue to say it. The the data the data manipulation.

Dominic:

You know, all all the database. And I'm I'm not a fan of ORM, don't get me wrong here. But still, I mean, I I I don't I haven't found something that I'm really in love with to manipulate data. I'm talking about SQL. I mean, SQL database.

Dominic:

Yeah. Yeah. Database SQL as a package is is great. Don't don't get me wrong as well. But I mean, it's it's either too verbose or I don't really like what what what the option what I have as as options to, to talk to databases.

Chris:

Yeah. I would totally agree as well. And I think I've I've never really found a good ORM with Go. Whereas, at least with Java, like, it was I never had that problem. Like, any ORM that I used, I I seem to really enjoy, and I thought it was very easy to interact with.

Chris:

Whereas in Go, I've never found a good one.

Dominic:

Yeah. Maybe, maybe maybe sometimes. But, alright. So, Chris, thank thank you very much. It was it was, it was very interesting.

Dominic:

And, I mean, we will have a a couple of, of links in the show notes. And, and again, I mean, thank you thank you so much for accepting the offer.

Chris:

Oh, yeah. Thanks a lot for having me. It's been great.