Public read, authenticated write
Anyone can read. Only logged-in users can write..read rule is a plain true, so unauthenticated clients can read. The .write rule checks that auth is not null, meaning the client must be signed in to write. Good for public content like leaderboards, announcements, or game state that anyone can view.
User-owned data
Users can only read and write their own data.$uid wildcard captures the child key under /users. The rule compares it to auth.uid, so a user can only access the node that matches their own ID. No user can read or modify another user’s data.
Required fields validation
Ensure that every write includes specific fields..validate ensures both name and score are present. Each child has its own validation to enforce types and constraints. The $other rule with .validate: false rejects any fields that aren’t explicitly defined. This locks down your data shape tightly.
Type validation
Check that values are the correct type.isString(), isNumber(), and isBoolean() to enforce types. Chain them with range checks or length constraints using &&. This prevents clients from sending a string where you expect a number, or a negative value where you expect a positive one.
Role-based access
Use an admin flag stored in user data to gate sensitive operations./adminContent path checks the requesting user’s role field by reading from /users/{uid}/role via root.child(...). Only users whose role is 'admin' can read or write admin content. The role field itself can only be changed by an existing admin, preventing users from promoting themselves.
Game lobby pattern
Players can join a lobby by writing their own entry. Only the host can modify game settings. Anyone in the lobby can read all lobby data.- Read access: Only players already in the lobby can read its data. The rule checks if the authenticated user has an entry under
players/. - Settings: Only the host (whose UID matches the
hostfield) can update game settings likemaxPlayersandgameMode. - Host field: Locked down with
.write: falseat the client level. Set the host when creating the lobby via a server-side operation or initial write. - Players: Each player can write only their own entry (
auth.uid === $uid). Validation ensures every player entry has anameandreadystatus.
The host field should be set when the lobby is first created. You can do this by including
host in the initial write that creates the lobby, before per-field rules take effect. Alternatively, set it from a trusted server environment.Write-once data
Data can be created but never modified or deleted..write rule has two conditions: the user must be authenticated (auth !== null), and the data must not already exist (!data.exists()). Once a node is written, data.exists() becomes true and all future writes are rejected.
The .validate rule also requires newData.exists(), which prevents deletion. Without this, a client could delete the node (setting it to null) and then re-create it.
The timestamp validation ensures the timestamp is set to the server’s current time via now, preventing clients from backdating events.
Query-based access control
Restrict reads so clients must include specific query parameters. This prevents clients from downloading an entire collection when they should only access a subset.db.ref('orders').on('value', ...) without the filter is rejected. This is useful when you have a shared collection but each user should only see their own records.
You can also enforce size limits to prevent clients from downloading too much data at once:

