E-Commerce Microservices Backend with GraphQL Gateway
Build the backend of an online shop as three separate TypeScript services (products, users and orders), each with its own GraphQL API and database, joined behind a single Apollo Federation gateway. Clients send one query, such as "my orders with each product's name and price", and the gateway splits it across the services and combines the answer. Services own their data and extend each other's types: the orders service adds an orders field to a user, and the gateway asks the right service for each piece. Everything runs with Docker Compose. You'll learn GraphQL schema design, Apollo Federation (entities, keys and reference resolvers), sharing types across services, avoiding slow N+1 queries with DataLoader, and end-to-end testing across services.
- Estimate
- ~14.5h
- Steps
- 7
- Completed by
- 0
- Proposed by
- codeseed.app
Apollo Federation · GraphQL · Express · Docker
Project roadmap
- 01
Build the products service
~2.5hCreate a TypeScript service with Apollo Server and @apollo/subgraph, with its own database (SQLite or PostgreSQL through an ORM such as Prisma or Drizzle). Define a Product type with @key(fields: "id"), queries for products (with pagination) and product(id), and a __resolveReference resolver so other services can refer to products by id. Seed some products. Done when: the service answers product queries on its own.
- 02
Build the users and orders services
~3hCreate a users service with a User entity and a me query (the user id comes from a header for now). Create an orders service with its own Order type (id, items with quantity and price at the time, status, created at), a placeOrder mutation, and extensions: it adds an orders field to User and references Product by id in each order item. Done when: each service runs and answers its own queries.
- 03
Set up the gateway
~2hCompose the three subgraphs into a supergraph (with the Rover CLI or IntrospectAndCompose for development) and run an Apollo gateway (or Apollo Router) in front of them. Forward the user id header from the gateway to the services. Done when: one query at the gateway returns a user with their orders and each item's product name.
- 04
Make cross-service queries efficient
~2hLog how many database queries each service runs for a request listing 50 orders with products, and you'll see one query per product (the N+1 problem). Fix it with DataLoader in the products service, batching all product lookups in a request into one query. Validate that placeOrder checks prices on the server by querying products, never trusting prices from the client. Done when: the same request runs a constant, small number of queries.
- 05
Add errors and auth
~1.5hVerify a JWT at the gateway and pass the user id to services; services refuse me and placeOrder without it. Return GraphQL errors with clear codes (UNAUTHENTICATED, NOT_FOUND, BAD_USER_INPUT), and make sure a failing service returns partial data with an error instead of breaking the whole response. Done when: unauthenticated requests fail cleanly, and stopping one service still returns the other data.
- 06
Run everything with Docker Compose
~1.5hWrite a Dockerfile for each service and the gateway, and a docker-compose.yml with their databases, health checks and start order. Add a script that composes the supergraph and checks the schemas for breaking changes. Done when: docker compose up starts the whole system and the gateway answers queries.
- 07
Write end-to-end tests
~2hWrite tests (with Vitest or Jest) that start the services and gateway (or run against Docker Compose) and send queries to the gateway: listing products, a user's orders with product details, placing an order, authentication errors, and partial results when a service is down. Done when: the end-to-end tests pass.
Resources
Ready to build this?
Get a GitHub repo and start building. Your AI reviewer checks each step as you go.
Tech stack