Data validation

You can useFirebase Security Rules to conditionally write new data based on existing datain your database or storage bucket. You can also write rules that enforce datavalidations by restricting writes based on the new data being written. Read onto learn more about rules that use existing data to create security conditions.

Select a product in each section to learn more about data validation rules.

Restrictions on new data

Cloud Firestore

If you want to make sure that a document that contains a specific field isn'tcreated, you can include the field in theallow condition. For example, ifyou want to deny creation of any documents that contain theranking field,you would disallow it in thecreate condition.

  service cloud.firestore {    match /databases/{database}/documents {      // Disallow      match /cities/{city} {        allow create: if !("ranking" in request.resource.data)      }    }  }

Realtime Database

If you want to make sure that data that contains certain values isn't addedto your database, you'd include that value in your rules and disallow it forwrites. For example, if you want to deny any writes that containrankingvalues, you would disallow writes for any documents withranking values.

{"rules":{//Writeisallowedforallpaths".write":true,//Allowswritesonlyifnewdatadoesn't include a `ranking` child value      ".validate": "!newData.hasChild('ranking')    }  }

Cloud Storage

If you want to make sure that a file that contains specific metadata isn'tcreated, you can include the metadata in theallow condition. For example, ifyou want to deny creation of any files that containranking metadata,you would disallow it in thecreate condition.

  service firebase.storage {    match /b/{bucket}/o {      match /files/{fileName} {      // Disallow        allow create: if !("ranking" in request.resource.metadata)      }    }  }

Use existing data inFirebase Security Rules

Cloud Firestore

Many apps store access control information as fields on documents in the database.Cloud Firestore Security Rules can dynamically allow or deny access based on documentdata:

servicecloud.firestore{match/databases/{database}/documents{//Allowtheusertoreaddataifthedocumenthasthe'visibility'//fieldsetto'public'match/cities/{city}{allowread:ifresource.data.visibility=='public';}}}

Theresource variable refers to the requested document, andresource.data isa map of all of the fields and values stored in the document. For moreinformation on theresource variable, seethe referencedocumentation.

When writing data, you may want to compare incoming data to existing data. Thislets you do things like ensure a field hasn't changed, that a field has onlyincremented by one, or that the new value is at least a week in the future.In this case, if your ruleset allows the pending write, therequest.resourcevariable contains the future state of the document. Forupdate operations that onlymodify a subset of the document fields, therequest.resource variable willcontain the pending document state after the operation. You can check the fieldvalues inrequest.resource to prevent unwanted or inconsistent data updates:

servicecloud.firestore{match/databases/{database}/documents{//Makesureallcitieshaveapositivepopulationand//thenameisnotchangedmatch/cities/{city}{allowupdate:ifrequest.resource.data.population >0                      &&request.resource.data.name==resource.data.name;}}}

Realtime Database

InRealtime Database, use.validate rules to enforce data structures and validatethe format and content of data.Security Rules run.validate rules afterverifying that a.write rule grants access.

The.validate rules do not cascade. If any validation rule fails on anypath or subpath in the rule, the entire write operation will be rejected.Additionally, the validate definitions only check for non-null values, andsubsequently ignore any requests that are deleting data.

Consider the following.validate rules:

  {    "rules": {      // write is allowed for all paths      ".write": true,      "widget": {        // a valid widget must have attributes "color" and "size"        // allows deleting widgets (since .validate is not applied to delete rules)        ".validate": "newData.hasChildren(['color', 'size'])",        "size": {          // the value of "size" must be a number between 0 and 99          ".validate": "newData.isNumber() &&                        newData.val() >= 0 &&                        newData.val() <= 99"        },        "color": {          // the value of "color" must exist as a key in our mythical          // /valid_colors/ index          ".validate": "root.child('valid_colors/' + newData.val()).exists()"        }      }    }  }

Write requests to a database with the rules above would have the followingresults:

JavaScript
varref=db.ref("/widget");//PERMISSION_DENIED:doesnothavechildrencolorandsizeref.set('foo');//PERMISSIONDENIED:doesnothavechildcolorref.set({size:22});//PERMISSION_DENIED:sizeisnotanumberref.set({size:'foo',color:'red'});//SUCCESS(assuming'blue'appearsinourcolorslist)ref.set({size:21,color:'blue'});//Iftherecordalreadyexistsandhasacolor,thiswill//succeed,otherwiseitwillfailsincenewData.hasChildren(['color','size'])//willfailtovalidateref.child('size').set(99);
Objective-C
Note: This Firebase product is not available on the App Clip target.
FIRDatabaseReference*ref=[[[FIRDatabasedatabase]reference]child:@"widget"];// PERMISSION_DENIED: does not have children color and size[refsetValue:@"foo"];// PERMISSION DENIED: does not have child color[refsetValue:@{@"size":@"foo"}];// PERMISSION_DENIED: size is not a number[refsetValue:@{@"size":@"foo",@"color":@"red"}];// SUCCESS (assuming 'blue' appears in our colors list)[refsetValue:@{@"size":@21,@"color":@"blue"}];// If the record already exists and has a color, this will// succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])// will fail to validate[[refchild:@"size"]setValue:@99];
Swift
Note: This Firebase product is not available on the App Clip target.
varref=FIRDatabase.database().reference().child("widget")// PERMISSION_DENIED: does not have children color and sizeref.setValue("foo")// PERMISSION DENIED: does not have child colorref.setValue(["size":"foo"])// PERMISSION_DENIED: size is not a numberref.setValue(["size":"foo","color":"red"])// SUCCESS (assuming 'blue' appears in our colors list)ref.setValue(["size":21,"color":"blue"])// If the record already exists and has a color, this will// succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])// will fail to validateref.child("size").setValue(99);
Java
FirebaseDatabasedatabase=FirebaseDatabase.getInstance();DatabaseReferenceref=database.getReference("widget");// PERMISSION_DENIED: does not have children color and sizeref.setValue("foo");// PERMISSION DENIED: does not have child colorref.child("size").setValue(22);// PERMISSION_DENIED: size is not a numberMap<String,Object>map=newHashMap<String,Object>();map.put("size","foo");map.put("color","red");ref.setValue(map);// SUCCESS (assuming 'blue' appears in our colors list)map=newHashMap<String,Object>();map.put("size",21);map.put("color","blue");ref.setValue(map);// If the record already exists and has a color, this will// succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])// will fail to validateref.child("size").setValue(99);
REST
# PERMISSION_DENIED: does not have children color and sizecurl -X PUT -d 'foo' \https://docs-examples.firebaseio.com/rest/securing-data/example.json# PERMISSION DENIED: does not have child colorcurl -X PUT -d '{"size": 22}' \https://docs-examples.firebaseio.com/rest/securing-data/example.json# PERMISSION_DENIED: size is not a numbercurl -X PUT -d '{"size": "foo", "color": "red"}' \https://docs-examples.firebaseio.com/rest/securing-data/example.json# SUCCESS (assuming 'blue' appears in our colors list)curl -X PUT -d '{"size": 21, "color": "blue"}' \https://docs-examples.firebaseio.com/rest/securing-data/example.json# If the record already exists and has a color, this will# succeed, otherwise it will fail since newData.hasChildren(['color', 'size'])# will fail to validatecurl -X PUT -d '99' \https://docs-examples.firebaseio.com/rest/securing-data/example/size.json
Note: Validation rules are not meant to completely replace data validation codein your app. We recommend that you also perform input validation client-sidefor best performance and best user experience when your app is offline.

Cloud Storage

When evaluating rules, you may also want to evaluate the metadata of the filebeing uploaded, downloaded, modified, or deleted. This lets you createcomplex and powerful rules that do things like only allow files with certaincontent types to be uploaded, or only files greater than a certain size to bedeleted.

Theresource object contains key-value pairs with file metadata surfaced in aCloud Storage object. These properties can be inspected onread orwrite requests to ensure data integrity. Theresource object checks metadataon existing files in yourCloud Storage bucket.

servicefirebase.storage{match/b/{bucket}/o{match/images{match/{fileName}{//Allowreadsifacustom'visibility'fieldissetto'public'allowread:ifresource.metadata.visibility=='public';}}}}

You can also use therequest.resource object onwrite requests (such asuploads, metadata updates, and deletes. Therequest.resource object getsmetadata from the file that will be written if thewrite is allowed.

You can use these two values to prevent unwanted or inconsistent updatesor to enforce application constraints, such as file type or size.

servicefirebase.storage{match/b/{bucket}/o{match/images{//Allowwritefilestothepath"images/*",subjecttotheconstraints://1)Fileislessthan5MB//2)Contenttypeisanimage//3)Uploadedcontenttypematchesexistingcontenttype//4)Filename(storedinimageIdwildcardvariable)islessthan32charactersmatch/{imageId}{allowread;allowwrite:ifrequest.resource.size <5*1024*1024                       &&request.resource.contentType.matches('image/.*')                       &&request.resource.contentType==resource.contentType                       &&imageId.size() <32}}}}

A full list of properties in theresource object is available in thereference documentation.

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2026-02-18 UTC.