Understanding API Gateways and Their Role in Microservice Architectures

This article explains what an API gateway is, why it is essential in microservice architectures, and how it handles cross‑cutting concerns such as authentication, transport security, load balancing, request routing, dependency resolution, and data transformation, illustrated with a simple Node.js gateway example and code snippets.

Architects Research Society
Architects Research Society
Architects Research Society
Understanding API Gateways and Their Role in Microservice Architectures

In this article we discuss API gateways and how they help solve important problems in microservice‑based architectures, building on the first article of the series.

What Is an API Gateway and Why Use It?

API gateways sit in the upper layer of the software stack and address shared cross‑cutting concerns across services, such as authentication, transport security, load balancing, request routing (including fault tolerance and service discovery), dependency resolution, and transport transformation.

Authentication

Most gateways perform authentication for each request, routing the request to the appropriate microservice or returning an error. They often add authentication information to the request before forwarding it, enabling downstream services to implement user‑specific logic.

Transport Security

Gateways act as a single entry point for public APIs, handling transport security (e.g., SSL termination) before forwarding requests to internal services over non‑SSL connections.

Load Balancing

Under high load, a gateway can distribute requests among microservice instances based on custom logic, taking into account each service’s scaling limits.

Request Routing

Gateways provide custom routing logic, cooperating with service registration/discovery mechanisms to dynamically route requests, support failover to backup services, and enable flexible request handling.

Dependency Resolution

Gateways can present a virtual endpoint that aggregates calls to many internal services, reducing the chatter between microservices.

Transport Transformation

Because microservices may use different data formats, gateways perform necessary transformations so that clients can communicate with the underlying services.

API Gateway Example (Node.js)

The following simple Node.js gateway handles HTTP requests, performs authentication with JWT, and forwards requests to internal endpoints while applying required transformations.

/*
 * Simple login: returns a JWT if login data is valid.
 */
function doLogin(req, res) {
  getData(req).then(function(data) {
    try {
      var loginData = JSON.parse(data);
      User.findOne({ username: loginData.username }, function(err, user) {
        if (err) { logger.error(err); send401(res); return; }
        if (user.password === loginData.password) {
          var token = jwt.sign({ jti: uuid.v4(), roles: user.roles }, secretKey, {
            subject: user.username,
            issuer: issuerStr
          });
          res.writeHeader(200, { 'Content-Length': token.length, 'Content-Type': "text/plain" });
          res.write(token);
          res.end();
        } else {
          send401(res);
        }
      }, 'users');
    } catch (err) {
      logger.error(err);
      send401(res);
    }
  }, function(err) {
    logger.error(err);
    send401(res);
  });
}

/* Authentication validation using JWT. Strategy: find existing user. */
function validateAuth(data, callback) {
  if (!data) { callback(null); return; }
  data = data.split(" ");
  if (data[0] !== "Bearer" || !data[1]) { callback(null); return; }
  var token = data[1];
  try {
    var payload = jwt.verify(token, secretKey);
    if (!payload.jti || revokedTokens[payload.jti]) {
      logger.debug('Revoked token, access denied: ' + payload.jti);
      callback(null);
    } else {
      callback({ jwt: payload });
    }
  } catch (err) {
    logger.error(err);
    callback(null);
  }
}

Transport Security

Transport security is handled via TLS; public requests first hit a reverse Nginx proxy with a sample certificate.

Dynamic Routing, Data Aggregation, and Fault Handling

Requests are dynamically scheduled based on configuration stored in a database, supporting both HTTP and AMQP. The gateway can aggregate responses from multiple internal services into a single JSON payload.

/*
 * Parses the request and dispatches multiple concurrent requests to each internal endpoint.
 * Results are aggregated and returned.
 */
function serviceDispatch(req, res) {
  var parsedUrl = url.parse(req.url);
  Service.findOne({ url: parsedUrl.pathname }, function(err, service) {
    if (err) { logger.error(err); send500(res); return; }
    var authorized = roleCheck(req.context.authPayload.jwt, service);
    if (!authorized) { send401(res); return; }
    var promises = [];
    service.endpoints.forEach(function(endpoint) {
      logger.debug(sprintf('Dispatching request from public endpoint %s to internal endpoint %s (%s)', req.url, endpoint.url, endpoint.type));
      switch (endpoint.type) {
        case 'http-get':
        case 'http-post':
          promises.push(httpPromise(req, endpoint.url, endpoint.type === 'http-get'));
          break;
        case 'amqp':
          promises.push(amqpPromise(req, endpoint.url));
          break;
        default:
          logger.error('Unknown endpoint type: ' + endpoint.type);
      }
    });
    Q.allSettled(promises).then(function(results) {
      var responseData = {};
      results.forEach(function(result) {
        if (result.state === 'fulfilled') {
          responseData = _.extend(responseData, result.value);
        } else {
          logger.error(result.reason.message);
        }
      });
      res.setHeader('Content-Type', 'application/json');
      res.end(JSON.stringify(responseData));
    });
  }, 'services');
}

Role Check

var User = userDb.model('User', new mongoose.Schema({ username: String, password: String, roles: [String] }));
var Service = servicesDb.model('Service', new mongoose.Schema({
  name: String,
  url: String,
  endpoints: [new mongoose.Schema({ type: String, url: String })],
  authorizedRoles: [String]
}));
function roleCheck(jwt_, service) {
  var intersection = _.intersection(jwt_.roles, service.authorizedRoles);
  return intersection.length === service.authorizedRoles.length;
}

Logging

Logging is centralized: all logs are published to the console and an internal message bus, where other services can react.

Conclusion

API gateways are a vital component of any microservice‑based architecture, providing a convenient, unified way to handle cross‑cutting concerns such as authentication, load balancing, dependency resolution, data transformation, and dynamic request routing, allowing individual microservices to focus on their core responsibilities and accelerate development.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

load balancingNode.jsapi-gatewayAuthentication
Architects Research Society
Written by

Architects Research Society

A daily treasure trove for architects, expanding your view and depth. We share enterprise, business, application, data, technology, and security architecture, discuss frameworks, planning, governance, standards, and implementation, and explore emerging styles such as microservices, event‑driven, micro‑frontend, big data, data warehousing, IoT, and AI architecture.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.