NGINX’s map module creates a variable whose value is chosen from another variable, such as a host name, request header, URI, or client address. Put an HTTP map in the http {} context, define a deliberate default, and then consume the resulting variable in a directive such as add_header, routing, redirection, or connection limiting. The crucial behavior is deterministic precedence: exact strings win first, then hostname masks, then regular expressions in file order, and finally default.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
What the NGINX map module does
The official HTTP reference describes ngx_http_map_module as creating “variables whose values depend on values of other variables.” A map is therefore a value-selection table, not an action by itself. One variable supplies the input; a second variable receives the selected result; another directive decides what to do with that result.
As an Amazon Associate I earn from qualifying purchases.
Recommended Free Tools
The declaration has this shape:
map string $variable {
...
}
For HTTP configuration, the block belongs in http {}. You can place it directly there or in a file included from that context. A map may use one or more variables as its source value. The result variable is evaluated when a directive actually uses it, so declaring a large map does not by itself add request-processing work.
Your first HTTP map
This example classifies requests by host and exposes the result as a response header:
#1 Best Overall
http {
map $http_host $site_class {
default other;
example.com primary;
*.example.com subdomain;
}
server {
listen 80;
add_header X-Site-Class $site_class;
}
}
The map reads $http_host. For an exact example.com request it produces primary; for a matching subdomain it produces subdomain; every other value receives other. The server block does not redefine the map. It simply consumes $site_class like any other NGINX variable.
- Put the
mapblock insidehttp {}, or in an include file loaded from that context. - Choose the source variable, such as
$host,$http_host,$request_uri, or a custom header variable. - Name the result variable (for example,
$site_class). - Add exact values, masks, regular expressions, and a
defaultresult. - Reference the result in the directive that needs the decision.
$host is often preferable for host policy because it represents NGINX’s normalized host value, while $http_host is the incoming HTTP header. Select the source that matches the policy you are implementing.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
How NGINX chooses a matching entry
When several entries could match, NGINX stops at the first match in a fixed order. This order, rather than the visual order of unrelated entries, determines the result:
| Priority | Entry type | Behavior |
|---|---|---|
| 1 | Exact string without a mask | Literal strings are compared without regard to case. |
| 2 | Longest prefix mask | For example, a hostname pattern such as *.example.com; the most specific matching prefix wins. |
| 3 | Longest suffix mask | For example, mail.*; the longest matching suffix wins. |
| 4 | Regular expression | The first matching regex in the order written wins. |
| 5 | default |
Used only when no exact, mask, or regex entry matches. |
Regular-expression keys begin with ~ for case-sensitive matching or ~* for case-insensitive matching. Regex order is significant: two matching expressions do not compete by specificity; the earlier one is selected.
Always decide what should happen for unmatched input. If you omit default, the map variable becomes an empty string. An explicit fallback makes the behavior visible and prevents an unexpected blank value from reaching a header, upstream choice, redirect, or policy check.
Hostname masks and the hostnames; parameter
Wildcard hostname matching is enabled by placing hostnames; before the value entries:
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallmap $host $allowed_host {
hostnames;
default 0;
example.com 1;
*.example.com 1;
}
With this form, example.com is explicitly allowed and *.example.com covers its subdomains. A wildcard subdomain entry should not be assumed to cover the bare domain; include both entries when both forms are intended. NGINX also supports combining the exact host and its subdomains as .example.com when hostnames; is enabled.
The hostnames; line must come before the value list. Without it, hostname prefix and suffix masks are not interpreted as hostname masks.
Mapping headers, URIs, and several input variables
Maps are useful whenever a request value needs to become a stable internal label. Common inputs include:
Rank #2
- Host names: classify tenants, sites, or allowed domains.
- Headers: turn a feature flag, API version, or tenant header into a route class.
- URIs: select a content type, cache policy, or handling class from a path.
- Other NGINX variables: combine request metadata into a value consumed later.
The source expression can contain one or more variables, while the result remains a normal NGINX variable. This lets one map centralize a decision instead of repeating long conditionals in several server or location blocks.
A large header-driven policy can be kept readable by moving records to a separate file:
map $http_x_tenant $backend_class {
include conf.d/tenant-map.conf;
default unknown;
}
The included file contains map entries, one per line. Multiple include directives are allowed, so teams can split records by tenant group or deployment responsibility while keeping the map declaration in the main configuration.
Regular expressions and captures
A regex entry can return a fixed value or a capture from the match. Named captures create ordinary NGINX variables that can be used later alongside the mapped result. Positional captures are available as $1 through $9.
map $uri $image_ext {
default "";
~^/images/.+.(?<ext>jpg|png)$ $ext;
}
For a URI such as /images/banner.png, the named capture $ext contains png, and the map result is that value. The regex key starts with ~, so matching is case-sensitive; use ~* when case-insensitive matching is required.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Positional captures share a request or connection capture set. A later regex operation can replace those positions, which makes an earlier $1 fragile when several directives perform matching. Prefer named captures when another directive needs a stable value. Check the regex syntax and capture behavior against the PCRE support in the NGINX build you will deploy.
Parameters that change map behavior
| Parameter | Purpose | Placement or availability |
|---|---|---|
default value; |
Supplies the result when no other entry matches. If omitted, the result is an empty string. | Inside the map value list. |
hostnames; |
Enables hostname prefix and suffix masks and the combined .example.com form. |
Inside the map, before value entries. |
include file; |
Loads mapping records from an external file. Multiple includes are permitted. | Inside the map value list. |
volatile; |
Marks the result variable as not cacheable. | Map parameter; available since NGINX 1.11.7. |
map_hash_bucket_size |
Tunes the hash bucket size used by maps. | http context; documented defaults are 32, 64, or 128 depending on cache-line size. |
map_hash_max_size |
Tunes the maximum map hash size. | http context; documented default is 2048. |
Use volatile; when the map result must not be cached. For ordinary request classification, the default non-volatile behavior is usually the intended choice. Hash-size directives affect map storage rather than matching precedence; change them only when your configuration requires different hash sizing.
Using a map result in other directives
A map does not redirect, proxy, allow, or deny by itself. It supplies a variable to a directive that performs that operation. Typical uses include:
- Response headers: expose a classification with
add_header X-Site-Class $site_class;. - Routing: derive a backend class from a host or header and pass that variable to a routing directive configured to accept variables.
- Redirects: map a request value to a destination or redirect class, then use the result in the relevant
returnpolicy. - Access decisions: map a request attribute to a flag such as
0or1, then feed that flag to the access-control design used by your configuration. The map only computes the flag. - Connection limits: in stream configuration, derive a limit key and provide it to
limit_conn_zone.
Keep the policy in the map and the action in the consuming directive. This separation makes overlapping rules easier to audit and lets several consumers share one decision variable.
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsEnd-to-end decision patterns
A host-to-route map follows the same pattern as the header example: map $host to a short backend label, set a safe fallback such as unknown, and pass that label to the routing directive that supports variables. The map should not silently turn an unknown host into a production backend. Make the fallback represent the behavior you actually want, such as a rejected request or a neutral service.
Rank #3
For a redirect policy, map a request value to a destination class rather than embedding a long chain of conditions in every location. Keep the result empty only when the consuming directive has an intentional meaning for an empty value; otherwise choose an explicit fallback. The same approach works for a response header: one map can classify a tenant, and several headers or logs can consume the same variable.
Access policies commonly map a header or other request attribute to 0 and 1. Treat that value as a policy input, not proof of identity: the directive that enforces access still determines whether the request is allowed. If the real input is an IP network, use geo instead of forcing network logic into text regexes.
HTTP maps versus stream maps
The stream module has the same general map declaration style, but its context is stream {}, not http {}. Stream maps are for connection-oriented values rather than HTTP request variables. The official stream example maps $remote_addr to a $limit variable and then feeds that variable to limit_conn_zone.
stream {
map $remote_addr $limit {
default 1;
}
limit_conn_zone $limit zone=connection_limit:10m;
}
This illustrates the division of scope: an HTTP map belongs under http and can read HTTP variables; a stream map belongs under stream and produces connection-level values. Do not place a stream map in an HTTP block or expect an HTTP-only variable to exist in stream context.
Map, geo, and numeric-range alternatives
Choose the module according to the input domain, not merely the fact that all three produce variables.
| Decision axis | map |
geo |
num_map |
|---|---|---|---|
| Best input | Strings, hostnames, headers, URIs, and regular expressions. | IP-network classification. | Numeric ranges. |
| Evaluation | Result is evaluated when the variable is used. | Designed for address-based classification. | Designed for numeric-range matching. |
| Precedence control | Exact values, masks, regex order, then default. | Uses its own address-range rules. | Uses numeric-range rules. |
| Typical scope | HTTP request policy or stream connection policy, depending on context. | Address policy. | Numeric policy. |
Use geo when the central question is whether an address belongs to a network. Use the current num_map module when the input is a numeric range. Use map when text matching, hostname masks, or ordered regular expressions express the policy naturally.
Keeping large maps maintainable
For a short map, keeping entries inline makes review easy. For hundreds or thousands of records, put the data in an included file and leave the declaration, source variable, and fallback visible in the main configuration. Keep a deliberate default even when the include is expected to contain every known value; new or malformed input should have a defined outcome.
Document whether entries are exact, masks, or regexes. Review regex order whenever a new expression is added, because the first matching regex wins. For host policies, place hostnames; first and include the bare domain explicitly when it must be treated like its subdomains.
Separate policy data from mechanics: the main file should show the source variable, result variable, context, and fallback, while the included file can hold changing tenant records. Multiple includes are legal, but overlapping records still obey the same precedence rules. An include does not create a new scope or change whether an entry is exact, masked, or a regex.
Rank #4
Troubleshooting a map that returns the wrong value
The variable is empty
Check whether the input matched anything and whether a default entry exists. An omitted default intentionally produces an empty string. Also verify that the consuming directive is using the result variable, not the source variable.
A wildcard host does not match
Confirm that hostnames; appears before the entries. Check whether the request is for the bare domain or a subdomain; add both example.com and *.example.com, or use the combined .example.com form where appropriate.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →A regex result is unexpected
Inspect the order of regex entries. NGINX uses the first matching expression, not the most specific one. Then check whether the key begins with ~ or ~* as intended and whether a later match has overwritten a positional capture. Replace $1-style references with named captures when the value must survive other regex operations.
The map is in the wrong scope
An HTTP map must be declared in http {} or an include loaded there. A stream map must be declared in stream {}. Moving a block into a server or location context does not make it valid.
A large map behaves like a performance problem
Map declarations are evaluated lazily: the declaration itself does not add request-processing work until the result is used. If hash sizing needs adjustment, use map_hash_bucket_size or map_hash_max_size in the http context, while leaving matching rules and policy data unchanged.
The wrong rule wins
First determine the category of each candidate. An exact entry beats every mask and regex, the longest applicable prefix or suffix mask beats shorter masks, and only then are regexes considered. Among regexes, line order is decisive. Reordering two regex lines can therefore change behavior without changing either expression.
Testing a mapping before relying on it
Build a small table of representative inputs and expected outputs. Include the exact host, a first-level subdomain, a deeper subdomain, an unrelated host, uppercase and lowercase forms, a value that should match each regex, and an unmatched value that must reach default. For a URI map, test both matching extensions and paths that merely contain a similar substring. For a header map, test a missing header as well as an unexpected value.
When captures are involved, verify both the mapped variable and the named capture consumed later. Test configurations in the same NGINX build and context in which they will run, because stream and HTTP variables are not interchangeable and regex support depends on the installed PCRE integration. Treat a changed include file as a policy change: review overlaps and fallback behavior, not just syntax.
A practical design checklist
- Is the input a string or hostname that belongs in
map, rather than an IP network forgeoor a numeric range fornum_map? - Is the map declared in the correct context:
httpfor HTTP requests orstreamfor connections? - Does the map have an explicit, safe
default? - For hostnames, is
hostnames;the first line before the entries? - Have you checked exact values, mask specificity, regex order, and case sensitivity?
- Are named captures used when a regex-derived value is needed later?
- Would an external
includefile make a large mapping easier to review? - Is
volatile;genuinely required, or is ordinary result caching appropriate? - Does the consuming directive accept the mapped variable and implement the action you want?
- Have you tested the bare hostname, wildcard hostname, unmatched input, and every overlapping regex?
Bottom line
Use NGINX map as a centralized, lazily evaluated decision table. Declare it in the correct top-level context, provide a deliberate fallback, and design around its precedence rules: exact strings, longest masks, first regex, then default. Add hostnames; for wildcard host policies, use named captures for reusable regex data, move large lists into includes, and choose geo or num_map when the input is an IP network or numeric range rather than text.
Best Value
Frequently Asked Questions
Where does an NGINX HTTP map block go?
Place it directly inside http {}, or in a file included from that context. A server or location block is not a valid location for the map declaration.
Free tools Windows power users keep installed
One-click scans. No signup required.
What happens if no map entry matches?
If you define default value;, that value is returned. If you omit default, the result variable is an empty string.
Which map rule wins when exact, wildcard, and regex entries overlap?
NGINX selects an exact unmasked string first, then the longest prefix mask, then the longest suffix mask, then the first matching regular expression in file order, and finally default.
Do wildcard host entries include the bare domain?
Do not assume they do. Include both example.com and *.example.com, or use the combined .example.com form with hostnames; when both should match.
What is the difference between ~ and ~* in a map key?
~ starts a case-sensitive regular expression; ~* starts a case-insensitive regular expression.
Recommended Free Tools
Can a map choose an upstream, redirect, header, or access result?
Yes, as an input to another directive that accepts variables. The map computes a label, destination, or flag; the consuming directive performs the routing, redirect, header, or access action.
Should I use named or positional regex captures?
Both are supported, but named captures are safer when a value is needed later. Positional $1 through $9 share a request or connection capture set and can be overwritten by a later regex operation.
When should I use geo or num_map instead of map?
Use geo for IP-network classification and num_map for numeric ranges. Use map for strings, hostnames, headers, URIs, and regular expressions.
Does a large map slow every request?
The map result is evaluated when it is used, so merely declaring a large map does not add request-processing work. If hash storage needs tuning, adjust map_hash_bucket_size or map_hash_max_size in the http context.
Free tools Windows power users keep installed
One-click scans. No signup required.
When is volatile; appropriate?
Use volatile; when the result must not be cached. It is available beginning with NGINX 1.11.7; ordinary request classification generally uses the default cacheable behavior.
The Bottom Line
Declare map in the right context, define an explicit fallback, and rely on its fixed precedence: exact value, longest mask, first regex, then default. Use hostnames; and named captures deliberately, externalize large lists with include, and choose geo or num_map when the input is an address network or numeric range.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




