Querying a Local GraphQL Microservice
Question: How can I work on just my microservice without also running a Gateway and all of the other related services?
Answer: Just like it works in Production
OK, so that’s a cheeky answer. In production, you have a Gateway, and you have all of the other services. What I mean by this is: your service doesn’t know any of that. It doesn’t know it’s part of a Gateway. It just knows how to respond to queries, just like every other GraphQL server. Let’s take this a step at a time, and I can show you what I mean:
Let’s assume the following super-simple Users service schema:
And you have another Movies service:
And now you want to add the user’s favorite movie.
favoriteMovie could be added in either service. In real life it would probably make more sense to be owned by the Movie Service, but that didn’t fit what I wanted to teach you as well, so this is what you get.
Step 1: Make Movie federable (federatable?):
We need to add a lookup key for Movie:
Step 2: Add the favoriteMovie to the user:
Here we add the user’s favorite movie, and we also stub out the Movie type.
Great! Now we can spin up the whole world (an Apollo Gateway, the Users service, and the Movies service) and test this thing out. You can make calls to the Gateway, and it proxies the whole thing and stitches it all together:
Now you will do this and this is how you will build stuff. The end.
OK. This is where my complaint is. This is what this article is about. The problem here is that you’re no longer thinking in microservices. You’re building and developing against a distributed monolith. Microservices are meant to work in isolation, and developing against a microservice means you should be developing against a contract, NOT against another service.
Who cares? This works
OK. Maybe it works today. Maybe you’ll never mind. But I can tell you that for most people, as the team gets bigger, you’re going to mind. One day someone is going to break the build. Someone is going to corrupt your Apollo Gateway server or one of your other services, and you’re going to be stuck, unable to work because you just finished a giant merge and you don’t want to go backward. Now you just wait.
There is a better way.
docker-compose down and let’s try something. Trust me.
Locally querying against users service
Start up your users service. If you’re actively building the users service, you should be able to use its API:
The only field you can ask for here on the Movie is the
id, as that’s all you have. This is your contract, and it’s amazing to get to work against JUST your contract.
You’ve already tested that it all connects through the Gateway. You don’t need to keep doing that anymore. You’re working on the users service. The other fields “don’t exist” anymore.
Locally querying against movies service
Now shut down the users service and start up the movies service. Let’s query for one of those:
But wait, there’s more to your contract, yeah? You’re here because you need to test and make sure that your
__resolveReference methods are working, and that everything will play nice, right? So back to my answer:
Do it like in Production
Well, what does production do? Your request comes in through Apollo Gateway, which makes makes a call to your users service:
And then it turns around with that
user.favoriteMovie.id and makes the following call to your movies service:
with the following variables
So now you can just make those calls. “Just” call into your
_entities and ask for the values you want.