ACL Selectors: Granular Permissions Beyond Simple Command Lists
AI generated
SET
TTL
Redis · Security · ACL
ACL Selectors
granular permissions beyond simple command lists

A classic Redis ACL rule defines a list of allowed commands and a single key pattern for a user. That covers simple roles, but breaks down as soon as a user needs different access rights to different key ranges depending on the command group. ACL selectors solve exactly this problem by allowing several independent permission rules within the same user. How selectors work technically, and how they can express a realistic multi-team setup, is what this article covers.

11 min read ACL SETUSER · Selectors Redis 7 · Redis 8 · Multi-Team

1. Where classic ACL rules hit their limits

A Redis ACL definition without selectors consists of exactly one rule set per user: a list of allowed or denied commands, combined with one or more key patterns that apply equally to all allowed commands. This works well as long as a user has a homogeneous role, for instance being allowed to only read, or to only write within a specific key range.

As soon as a user needs more differentiated rights, though, such as read access to a broad key range but write access only to a narrow subset, or administrative commands only for keys belonging to a specific team, a single rule set is no longer enough. Before Redis 7, such cases had to be solved either with several separate users and application logic to pick the right connection, or by accepting unnecessarily broad rights as a compromise.

2. The basic principle: multiple independent rule sets per user

An ACL selector is an additional, parenthesized rule block within an ACL SETUSER definition that defines its own, independent set of allowed commands and key patterns. A user can have any number of selectors in addition to its root rule set, which sits outside the parentheses. For every command, Redis checks whether either the root rule set or at least one of the defined selectors allows the command against the keys it touches.

Importantly, a selector is evaluated as a fully self-contained unit: a command must be entirely allowed within a single selector, and rights from different selectors are never combined for the same command invocation. This prevents several individually narrow selectors from accidentally combining into an overly broad permission.


# Create a user with a root rule set plus one additional selector
ACL SETUSER team_checkout on >secretpass \
    ~checkout:* +get +set +del \
    "(~orders:* +get +hget +hgetall)"

# Root rule set: full read/write access to checkout:*
# Selector: read-only access to orders:*

3. Combining multiple selectors: different rights per command group

A user can hold several selectors at once, each with its own commands and key patterns. This makes it possible to express real role models where different command groups have different access scopes: for example read access to order data for reporting purposes, write access to a narrow set of status fields for status transitions, and administrative access to job-control keys, each with its own pattern and command list.

In practice this means: instead of maintaining a separate user with a separate password for every combination of role and access scope, a single, semantically meaningful user can be defined whose selectors precisely express the actually needed access patterns. That significantly reduces the number of credentials to manage, without compromising on rights.


# A user with three independent selectors for different tasks
ACL SETUSER order_service on >secretpass \
    "(~orders:*:status +get +set)" \
    "(~orders:* +get +hgetall +mget)" \
    "(~jobs:orders:* +lpush +lpop +llen)"

4. Key-pattern precision per selector: why it makes a difference

Each selector defines its own set of key patterns via ~pattern for combined read and write access, or separately via %R~pattern for read-only access and %W~pattern for write-only access on a pattern. This fine-grained control makes it possible to distinguish between read and write rights on overlapping or separate key ranges within a single selector, without needing an additional selector for that.

In practice, this precision is essential for the principle of least privilege: a reporting service typically only needs %R~orders:*, while an order-service process responsible for status transitions specifically needs %W~orders:*:status, but must never have write access to full order records. Without this separation, teams would have to either grant overly broad write rights or maintain unnecessarily many users.


# Separate read and write rights within a single selector
ACL SETUSER reporting_readonly on >secretpass \
    "(%R~orders:* +get +hgetall +mget)"

# Write access to status fields only, no read access to full records
ACL SETUSER status_writer on >secretpass \
    "(%W~orders:*:status +set +hset)"

5. Practical example: a multi-team setup with three services

In a typical Magento-adjacent setup, several services share the same Redis instance for different purposes: a checkout service manages cart state, a reporting service reads historical order data for dashboards, and a job scheduler drives asynchronous processing queues. Without selectors, each of these services would either need its own narrow, single-purpose user, or all services would share an overly broad common user.

With selectors, a single user can be defined per service whose root rule set and additional selectors express exactly the combination of access patterns that service actually needs. The following example shows three users sharing the same Redis instance but with strictly separated access scopes.


# Checkout service: full access to carts, read-only access to prices
ACL SETUSER svc_checkout on >pass1 \
    "(~cart:* +get +set +hset +hgetall +expire)" \
    "(%R~price:* +get +mget)"

# Reporting service: read-only access to order data and metrics
ACL SETUSER svc_reporting on >pass2 \
    "(%R~orders:* +get +hgetall +mget +scan)" \
    "(%R~metrics:* +get +mget)"

# Job scheduler: full control over queues, no access to customer data
ACL SETUSER svc_scheduler on >pass3 \
    "(~jobs:* +lpush +lpop +llen +brpop)"

6. Evaluation order: how Redis decides across multiple selectors

For every command, Redis first checks whether the user's root rule set allows the command against the keys it touches. If not, the defined selectors are checked in order until either one selector fully allows the command or all selectors are exhausted. If no matching permission is found, the command is rejected with NOPERM, regardless of how narrowly a single selector missed allowing it.

Importantly, within a single selector, both the command and every key it touches must match that selector's key pattern. A command touching multiple keys at once, such as MGET key1 key2, is only allowed if both keys match the pattern within the same selector. This prevents rights from accumulating into an unintended combination across multiple selectors.

7. Testing and diagnosis: verifying ACL rules before production use

Before deploying a new user with multiple selectors, it is worth running a targeted test with ACL DRYRUN, which simulates whether a given command with given keys would be allowed for a user, without actually executing the command. This makes it possible to systematically verify complex selector combinations against an application's actually expected access patterns before the user is used in production.

Additionally, ACL LIST and ACL GETUSER provide a complete, machine-readable overview of all rules and selectors for a user, which is well suited for automated audits, for instance as part of a CI pipeline that checks, on every change to the ACL definitions, whether the actually granted rights still match the documented target state.


# Check whether svc_reporting would be allowed to run a write command
ACL DRYRUN svc_reporting SET orders:4711:status shipped
# -> "This user has no permissions to run the 'set' command"

# Print all rules including every defined selector
ACL GETUSER svc_reporting

8. Migration path: converting existing users to selectors step by step

For existing Redis installations with historically grown, overly broad user rights, a step-by-step migration is preferable to an abrupt rebuild. First, analyze via ACL LOG and application monitoring which commands and key patterns an existing user actually uses in practice, in order to derive precise selector definitions instead of guessing at rights broadly.

Next, create the new, selector-refined user alongside the old one, test it with the application in a staging environment, and only then switch the application over to the new user, while the old user temporarily remains as a fallback option before being removed for good.

9. Common mistakes when writing selector rules

A widespread mistake is forgetting the parentheses around a selector: without the enclosing parentheses, Redis simply interprets the rule as an extension of the root rule set instead of as a self-contained, independent selector, silently undoing the intended separation of access scopes. Just as common is forgetting to quote the entire selector string in shell scripts, which causes the shell to misinterpret the contained parentheses and spaces, making the command fail or, worse, produce an unintentionally different rule.

Another typical pitfall is assuming that a pattern allowed within a selector, such as +@read, will automatically also cover newly introduced read commands from future Redis versions, which is generally true but should still be regularly checked against the actually required commands for security-critical selectors, rather than blindly relying on command categories. Regularly cross-checking with ACL CAT, which lists all commands in a category, helps avoid surprises during a Redis upgrade.


# List all commands in the "read" category to verify selector scope
ACL CAT read

# Common mistake: missing parentheses turn the selector into the root set
ACL SETUSER broken_user on >pass ~orders:* +get +hget +hgetall
Aspect Classic ACL rule ACL selector Practical relevance
Rule sets per user Exactly one Any number in addition to the root set Selectors express real role models
Key-pattern granularity One pattern for all commands Own pattern per selector, even split read/write Finer-grained rights possible
Combining rights Not needed, only one set exists A command must be fully allowed within one selector Prevents unintended right combinations
Administrative effort Many users needed for many roles One user per service with several selectors Fewer credentials to maintain
Diagnosis ACL LIST is usually enough ACL DRYRUN and ACL GETUSER for selector detail Testability before production matters

Mironsoft

Cache layer setup and Magento Redis integration

Magento cache that isn't quite working or is misconfigured?

We set up Redis as a cache and session backend for Magento cleanly, tune memory usage and eviction strategies, and make sure full page cache and session storage work together reliably.

Redis Setup

Configure the cache, session, and FPC backend production-ready for Magento.

Memory Tuning

Match memory usage and eviction policies to the shop's actual load.

High Availability Setup

Set up Redis Sentinel or Cluster for resilient Magento environments.

10. Summary

ACL Selectors: The Essentials at a Glance

Baseline problem

A single rule set per user is not enough once different command groups need different access scopes.

Selector principle

Additional, parenthesized rule blocks allow several independent command and key-pattern combinations per user.

Precision

Separate read and write rights per selector via %R and %W enable least-privilege access even for complex roles.

Practical benefit

A multi-team setup with several services can be expressed with clearly separated, testable users instead of risky catch-all rights.

11. FAQ: ACL Selectors: The Essentials at a Glance

1What is an ACL selector in Redis?
An additional, parenthesized rule block within an ACL user definition that defines its own, independent set of allowed commands and key patterns, in addition to the user's root rule set.
2How many selectors can a user have?
Any number, in addition to its root rule set. For every command, Redis checks whether the root rule set or at least one of the selectors fully allows the command.
3Are rights from multiple selectors combined for one command?
No, a command must be fully allowed within a single selector. Rights from different selectors are never merged for the same command invocation.
4How can read and write rights be separated within a selector?
Via %R~pattern for read-only access and %W~pattern for write-only access on a given key pattern, instead of the general ~pattern covering both together.
5What problem do selectors solve compared to classic ACL rules?
They allow different command groups of the same user to have different access scopes, without needing to maintain several separate users for that.
6How can a permission case be tested before production use?
ACL DRYRUN simulates whether a given command with given keys would be allowed for a user, without actually executing the command.
7How do you display all rules and selectors of a user?
ACL GETUSER returns a complete, machine-readable overview of all rules including every selector defined for a user.
8What happens when a command touches keys matching different selectors?
The command is rejected unless all touched keys match the same selector's key pattern. Splitting the match across multiple selectors is not sufficient.
9How can a multi-team setup be expressed with selectors?
A user is defined per service with a root rule set and additional selectors that express exactly the combination of commands and key ranges that service actually needs.
10How do you migrate existing, overly broad users to selectors?
Step by step: first analyze the actually used commands and patterns via ACL LOG and monitoring, derive precise selectors from that, test in parallel, and only then switch over to production.