How to Leverage Nginx Lua for Aspect‑Oriented Backend Architecture

This article explains how to apply aspect‑oriented programming principles to a Ruby‑based API service by extracting cross‑cutting concerns such as request encryption, authentication, and permission checks into Nginx Lua middleware, enabling low‑coupling, scalable backend modules.

21CTO
21CTO
21CTO
How to Leverage Nginx Lua for Aspect‑Oriented Backend Architecture

Aspect‑oriented programming (AOP) separates code that solves domain‑specific problems from core business logic, improving maintainability.

Separating cross‑cutting concerns is the core concept of AOP. By isolating domain‑specific code, business logic no longer contains calls to that code; the relationship is encapsulated via aspects, making scattered changes easier to manage. – Wikipedia

Example requirements for a simplified APP backend project:

All client requests are encrypted; the server must verify integrity and detect tampering.

Login via phone number using a basic token mechanism.

Enterprise, group, and employee hierarchy must support future sharding or clustering.

Provide permission‑aware REST APIs (similar to PostgREST but extended).

Version 1 – Initial Design

The primary concern is a REST‑style resource server. Additional cross‑cutting concerns include request encryption validation, login verification, and permission management.

All request encryption validation

Login verification

Resource permission handling

In Sinatra, extensions can implement request encryption validation, combined with a before filter for uniform processing:

The approach uses middleware (a cross‑cutting concern layer) to intercept illegal requests.

Subsequent steps verify user login and retrieve organization information via helpers:

Thus, the REST implementation does not need to handle encryption or authentication directly; after validation and permission checks, it simply translates the request into database operations and returns the result.

Version 2 – Scaling with Nginx Lua

The first version isolates domain‑specific code, but real projects often require multi‑team, multi‑language development and rapid iteration, leading to independent low‑coupling servers. Communication between services can use internal web servers, TCP‑based RPC (e.g., Thrift), or message queues.

We chose Nginx’s Lua module to couple servers in an aspect‑oriented way.

Nginx Lua can connect to Redis, Memcached, PostgreSQL, read request data, set response headers/body, and run asynchronous scripts, enabling permission control and proxying.

Key directives used are proxy_pass and ngx.location.capture:

The code cleans malicious request headers and forwards the original request via request_to_server, then validates the response parameters.

Multiple internal addresses are configured using Nginx stream and proxy_pass:

Thus, Lua scripts can forward all request components (headers, body, URL, method) to another service and obtain the final result.

In the original Sinatra version, Ruby code handled the entire flow. By moving the flow to Nginx, the process becomes:

Incoming request is passed to request_to_server, which forwards it to services handling cross‑cutting concerns (authentication, organization).

Each service returns JSON; if it contains next: true, Nginx forwards the response headers to the next service.

If next: true is absent, Nginx returns the current service’s response directly.

This enables a chain of services where the final resource server receives enriched headers after successful authentication and organization lookup.

The system is split into three independent services:

User verification service (request encryption, login, password changes)

Organization service (enterprise hierarchy, permission retrieval)

Resource service (REST request handling)

Example flows:

If login fails, the verification service returns an error without next: true, so Nginx stops.

Sending an SMS code is handled solely by the verification service, again without next: true.

Successful login passes to the organization service, which returns detailed user info via headers.

A resource operation proceeds through verification → organization → resource services, each adding information via headers before the final proxy_pass to the resource server.

Advantages of this approach:

Leverages Nginx’s asynchronous model to compensate for Ruby’s I/O limitations.

Implements a linear processing chain (auth → org → resource) that can be extended by adding parameters to request headers, reducing coupling.

Each module can have its own caching and clustering strategy.

Facilitates isolated testing of individual services without extensive integration effort.

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.

aopNGINXLuacross-cutting-concernsSinatra
21CTO
Written by

21CTO

21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.

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.