Library / SDK
weibocom/nginx-upsync-module avatar
weibocom/nginx-upsync-module

nginx-upsync-module for Dynamic NGINX Upstreams

For http protocol. nginx-upsync-module, sync upstreams from consul or etcd and so on, dynamiclly modify backend-servers attributes(weight, max_fails, down...), needn't reload nginx

1,843 stars392 forksCLicense varies

At a glance

What is it?
nginx-upsync-module synchronizes HTTP upstream servers from Consul or etcd and changes backend attributes without reloading NGINX. It fits operators with registry-backed HTTP services, but compatibility and health-check requirements need verification.
Who is it for?
Operators running HTTP upstreams whose membership and load-balancing attributes are already represented in Consul or etcd should evaluate this module, while teams seeking a broadly documented service-discovery integration should first verify NGINX compatibility, build dependencies, health-check behavior, and recovery from an unavailable registry.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 18 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 6, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • weibocom/nginx-upsync-module1,843 ★ · -1
Star history
Repository2026-10-172026-11-06
weibocom/nginx-upsync-module1.8k1.8k

-1 Stars in the last 20 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Where nginx-upsync-module Fits in HTTP Service Discovery

nginx-upsync-module addresses a specific NGINX operational problem: backend membership can change more often than an operator wants to edit files and reload NGINX. It targets HTTP applications whose upstream servers are recorded in Consul, etcd, or a compatible source, and whose weights or availability flags may need to change while traffic is flowing. The module watches that source and applies the new server list to the relevant NGINX upstream without a configuration reload.

This is useful when a service registry already acts as the operational source of truth. For example, the README configures an upstream named `test` to read from `/v1/kv/upstreams/test/` in Consul or `/v2/keys/upstreams/test` in etcd. The registry key therefore carries more than a simple health state. It supplies backend addresses and attributes such as `weight` and `max_fails`, allowing discovery data and NGINX routing policy to stay connected.

The intended users are NGINX operators responsible for HTTP proxy configuration, service registration, and rollout coordination. It does not replace Consul or etcd. Those systems own the discovered data, while this module translates changes into the running NGINX process. It also does not cover the stream module used for TCP proxying. The README points readers to the separate `nginx-stream-upsync-module` for that protocol scope, which prevents a common mistake in which an HTTP synchronization module is expected to manage a TCP upstream.

There is a meaningful distinction between changing server attributes and checking whether each application can serve requests. Synchronization can add or remove an address represented by the registry, but the README says actual upstream health checking needs `nginx_upstream_check_module`. Organizations should not treat registry synchronization alone as proof of application health.

Consul and etcd Change Flow Inside an NGINX Upstream

The mechanism is based on long-running index-aware requests to Consul or etcd. According to the README, the module sends a key index with its pull. If the registry index has not changed, the connection can remain open for five minutes. A subsequent key operation returns promptly, allowing the module to obtain a changed upstream list without repeatedly polling a static endpoint.

An `upsync` directive lives inside an NGINX `upstream` block. Its address identifies the registry path and port, while `upsync_type` selects `consul` or `etcd`. `upsync_interval` controls how often servers are pulled, and `upsync_timeout` sets the request timeout. When those parameters are omitted, the documented defaults are `upsync_interval=5s`, `upsync_timeout=6m`, and `strong_dependency=off`.

The `strong_dependency` setting determines whether NGINX must pull from Consul or etcd whenever NGINX starts or reloads. The README recommends configuring it as off and ensuring that the included server file initially contains all servers. With that arrangement, NGINX can start from the dumped membership before a registry-backed pull completes. This is a meaningful startup dependency decision: strong coupling gives a fresh process an immediate registry pull, while the recommended configuration favors continued service from local state.

The module keeps the latest upstream membership in `upsync_dump_path`. The default is `/tmp/servers_$host.conf`. An `include` directive loads that generated file into the upstream. The dump is also a recovery mechanism when the registry is unavailable, because it gives NGINX local configuration representing the last known upstream list. The README does not document rollback behavior, conflict resolution between the dump and registry, or the atomicity of dump writes.

Configuring a Consul-Backed HTTP Upstream

The README's Consul example is the clearest first-use configuration. It creates an upstream named `test`, points `upsync` at the documented Consul key prefix, enables a dump file, and includes that file. It also defines a separate static upstream named `bar`, which makes clear that this module can coexist with conventionally configured upstreams.

The following configuration is copied from the README. It uses the documented Consul API path, a `500ms` synchronization interval, a `6m` timeout, and `strong_dependency=off`. The `upstream_show` location is included so the generated membership can be inspected through the documented endpoint.

nginx
http {
    upstream test {
        upsync 127.0.0.1:8500/v1/kv/upstreams/test/ upsync_timeout=6m upsync_interval=500ms upsync_type=consul strong_dependency=off;
        upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf;

        include /usr/local/nginx/conf/servers/servers_test.conf;
    }

    server {
        listen 8080;

        location = /proxy_test {
            proxy_pass http://test;
        }

        location = /upstream_show {
            upstream_show;
        }
    }
}

For the first real request, the README uses `proxy_pass` to enter the synchronized upstream. After data is present in the Consul path and NGINX has synchronized it, a request to the configured proxy location should be routed through the registered backends. That expected routing follows from the configuration and module description, but the README does not define the registry record format in full, so it should not be used as a complete data-authoring guide.

The operator can also request the upstream view. The documented examples query one named upstream and omit the query to list all upstreams. The request address contains `127.0.0.1:8500`, while the example server listens on `8080`; that mismatch should be checked against the local routing setup before treating the command as a drop-in test.

Inspecting and Selecting the Updated Load Balancer

The `upstream_show` directive exposes the backend servers for a specific upstream through an NGINX location. This is useful when an operator needs to confirm that registry changes reached the running process without waiting for an unrelated traffic failure. The README supplies two request forms, but the first uses port `8500` even though its sample NGINX server uses `listen 8080`, so endpoint configuration must be resolved locally.

The repository documents these inspection requests exactly:

bash
curl http://127.0.0.1:8500/upstream_list?test

With the upstream parameter, the request targets `test`. The README also documents a request without the parameter to show all upstreams:

bash
curl http://127.0.0.1:8500/upstream_list

Load-balancing behavior has one project-specific constraint. `upsync_lb` mainly exists for `least_conn` and consistent hash modes. The README states that selecting one of those modes requires the corresponding `upsync_lb` value. Its documented default list is `round_robin/ip_hash/hash modula`. For an upstream using `least_conn`, the configuration should make that choice explicit rather than assuming NGINX's ordinary upstream syntax is sufficient for dynamically inserted servers.

The README shows `upsync_lb least_conn;` paired with `least_conn;` in the upstream block. It also lists hash-related examples, including `//hash $uri consistent;` and `//hash_ketama;`. These comments indicate optional modes rather than a requirement for every deployment. The synchronization layer and the load-balancing layer perform different jobs: one obtains the current backend set, while the other determines how NGINX distributes requests.

Health Checks, Failure Recovery, and Missing Boundaries

The largest documented limitation is the separation between discovery and health checking. The README recommends combining `nginx-upsync-module` with `nginx_upstream_check_module` when servers need to be added or deleted according to health. This combination changes the adoption boundary. A team cannot assume that the C module alone continuously verifies application readiness, and the README does not document the health-check module's configuration.

A failed pull does not end synchronization. According to the README, the module attempts another pull after the next `upsync_interval`. The latest generated configuration is also available through `upsync_dump_path`, allowing NGINX to retain or reload the last known server set. That is useful for registry outages, but it is not the same as proven recovery behavior. The README does not state how stale data is detected, whether age is recorded, whether an operator can pin a known-good dump, or whether NGINX startup waits under each dependency mode.

Compatibility is another adoption concern. The README has a Compatibility section, but its contents are not reproduced here. It does not specify supported NGINX versions, supported architectures, build flags, or known incompatibilities. The Installation section is also present, but its commands are unavailable. No installation command can therefore be reproduced responsibly from this information. The repository layout contains `config`, `src`, `test`, and documentation files, but that alone does not establish a complete build procedure.

The last push was on 2026-10-16, so the repository is not archived. The listed releases are older: `v2.1.3` on 2020-11-20, `v2.1.2` on 2020-01-02, and `v2.1.1` on 2019-11-07. The repository description does not provide a dependency policy, migration notes, security update policy, or upgrade procedure. Operators must treat compatibility verification as part of adoption rather than assuming that the newest commit implies release support for their NGINX build.

Dynamic Synchronization Compared with Static NGINX Includes

The real alternative is the conventional NGINX approach: keep backend server directives in version-controlled configuration and reload NGINX after a deployment or registry change. That approach does not query Consul or etcd inside each upstream, but it has a simple source of truth and familiar NGINX behavior. It is a better fit when membership changes are rare, configuration review is mandatory, and restarting or reloading is acceptable.

`nginx-upsync-module` takes a different approach. It places a registry dependency inside the HTTP process, polls or watches changes, rewrites backend attributes at runtime, and maintains a generated include file. This removes the need to reload for each membership change, but it introduces synchronization timing, stale-state questions, and a dependency on registry API semantics. It also requires operators to reason about how a process starts when the registry is unavailable.

Static configuration is not automatically the better choice for high-churn HTTP fleets, since the README identifies repeated reloads under high load as a problem. Conversely, dynamic synchronization is not a drop-in improvement for every deployment. A small configuration with infrequent backend changes may gain little while accepting extra operational state. For TCP traffic, this module is the wrong scope, and the README directs users to `nginx-stream-upsync-module` instead.

Build, License, and Upgrade Cost for This C Module

No supported build recipe can be given from the visible README text. The project identifies itself as an NGINX C module, and the repository includes a `config` directory, but the Installation section does not show the required NGINX source path, compiler flags, linked libraries, or module ordering. Those details should be obtained from the project's full installation documentation before attempting a deployment build.

The repository's license is listed as unknown, and the README does not reproduce the copyright and license terms despite having a section for them. Source availability alone does not resolve whether an organization may compile, modify, redistribute, or operate the module. Any deployment needs a separate review of the repository's actual license file or authoritative project statement, without treating this article as legal advice.

Upgrades also require more than replacing the module binary. The relevant compatibility surface includes the NGINX version, Consul or etcd API behavior, optional health checking through `nginx_upstream_check_module`, generated `include` files, and startup behavior under `strong_dependency`. The listed releases and repository activity do not supply a migration guide for these combinations. Given that uncertainty, this project has a higher verification burden than a configuration-only NGINX change, especially for operators who cannot quickly restore the previous binary and server list.

Editorial conclusion

Operators running HTTP upstreams whose membership and load-balancing attributes are already represented in Consul or etcd should evaluate this module, while teams seeking a broadly documented service-discovery integration should first verify NGINX compatibility, build dependencies, health-check behavior, and recovery from an unavailable registry.

Frequently asked questions

Does nginx-upsync-module reload NGINX when upstream servers change?

No. The module dynamically adds, removes, or adjusts synchronized backend servers without reloading NGINX.

Which service discovery systems does nginx-upsync-module support?

The documented `upsync_type` values are `consul` and `etcd`. The README also refers to other compatible sources, but it does not detail them.

Does nginx-upsync-module perform backend health checks by itself?

The README says health checking requires `nginx_upstream_check_module` and recommends using it with `nginx-upsync-module`.

Official sources

  1. Issues
  2. README
  3. Releases
  4. weibocom/nginx-upsync-module on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/weibocom-nginx-upsync-module.svg)](https://hysenlabs.com/projects/weibocom-nginx-upsync-module)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/weibocom-nginx-upsync-module.svg)](https://hysenlabs.com/projects/weibocom-nginx-upsync-module)

Was this useful?