diff --git a/nuxeo-core/nuxeo-core-api/src/main/java/org/nuxeo/ecm/core/api/model/impl/AbstractProperty.java b/nuxeo-core/nuxeo-core-api/src/main/java/org/nuxeo/ecm/core/api/model/impl/AbstractProperty.java
index 5757ceb6164..aac4adddecf 100644
--- a/nuxeo-core/nuxeo-core-api/src/main/java/org/nuxeo/ecm/core/api/model/impl/AbstractProperty.java
+++ b/nuxeo-core/nuxeo-core-api/src/main/java/org/nuxeo/ecm/core/api/model/impl/AbstractProperty.java
@@ -21,6 +21,7 @@ package org.nuxeo.ecm.core.api.model.impl;
 
 import java.io.Serializable;
 import java.util.Iterator;
+import java.util.Optional;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -63,6 +64,13 @@ public abstract class AbstractProperty implements Property {
      */
     public static final int IS_SECURED = 64;
 
+    /**
+     * Whether or not this property is deprecated.
+     *
+     * @since 11.1
+     */
+    public static final int IS_DEPRECATED = 128;
+
     public final Property parent;
 
     /**
@@ -72,10 +80,6 @@ public abstract class AbstractProperty implements Property {
 
     protected int flags;
 
-    protected Boolean isDeprecated;
-
-    protected Property deprecatedFallback;
-
     protected AbstractProperty(Property parent) {
         this.parent = parent;
     }
@@ -355,36 +359,26 @@ public abstract class AbstractProperty implements Property {
     }
 
     protected boolean isDeprecated() {
-        if (isDeprecated == null) {
-            boolean deprecated = false;
-            // compute the deprecated state
-            // first check if this property is a child of a deprecated property
-            if (parent instanceof AbstractProperty) {
-                AbstractProperty absParent = (AbstractProperty) parent;
-                deprecated = absParent.isDeprecated();
-                Property parentDeprecatedFallback = absParent.deprecatedFallback;
-                if (deprecated && parentDeprecatedFallback != null) {
-                    deprecatedFallback = parentDeprecatedFallback.resolvePath(getName());
-                }
-            }
-            if (!deprecated) {
-                // check if this property is deprecated
-                String name = getXPath();
-                String schema = getSchema().getName();
-                SchemaManager schemaManager = Framework.getService(SchemaManager.class);
-                PropertyDeprecationHandler deprecatedProperties = schemaManager.getDeprecatedProperties();
-                deprecated = deprecatedProperties.isMarked(schema, name);
-                if (deprecated) {
-                    // get the possible fallback
-                    String fallback = deprecatedProperties.getFallback(schema, name);
-                    if (fallback != null) {
-                        deprecatedFallback = resolvePath('/' + fallback);
-                    }
-                }
-            }
-            isDeprecated = Boolean.valueOf(deprecated);
+        return areFlagsSet(IS_DEPRECATED);
+    }
+
+    /**
+     * Returns the {@link Property} fallback to use if the current property is deprecated.
+     *
+     * @return the fallback as {@link Property} if exist
+     */
+    protected Optional<Property> getDeprecatedFallback() {
+        if (parent instanceof AbstractProperty && ((AbstractProperty) parent).isDeprecated()) {
+            return ((AbstractProperty) parent).getDeprecatedFallback().map(p -> p.resolvePath(getName()));
         }
-        return isDeprecated.booleanValue();
+        if (isDeprecated()) {
+            SchemaManager schemaManager = Framework.getService(SchemaManager.class);
+            PropertyDeprecationHandler deprecatedProperties = schemaManager.getDeprecatedProperties();
+            String name = getXPath();
+            String schema = getSchema().getName();
+            return Optional.ofNullable(deprecatedProperties.getFallback(schema, name)).map(f -> resolvePath('/' + f));
+        }
+        return Optional.empty();
     }
 
     /**
@@ -437,16 +431,17 @@ public abstract class AbstractProperty implements Property {
     protected void setValueDeprecation(Object value, boolean setFallback) throws PropertyException {
         if (isDeprecated()) {
             // First check if we need to set the fallback value
-            if (setFallback && deprecatedFallback != null) {
-                deprecatedFallback.setValue(value);
+            Optional<Property> deprecatedFallback = getDeprecatedFallback();
+            if (setFallback) {
+                deprecatedFallback.ifPresent(p -> p.setValue(value));
             }
             // Second check if we need to log deprecation message
             if (log.isWarnEnabled()) {
                 StringBuilder msg = newDeprecatedMessage();
                 msg.append("Set value to deprecated property");
-                if (deprecatedFallback != null) {
-                    msg.append(" and to fallback property '").append(deprecatedFallback.getXPath()).append("'");
-                }
+                deprecatedFallback.ifPresent(
+                        p -> msg.append(" and to fallback property '").append(p.getXPath()).append("'"));
+
                 if (log.isTraceEnabled()) {
                     log.warn(msg, new NuxeoException("debug stack trace"));
                 } else {
@@ -489,14 +484,15 @@ public abstract class AbstractProperty implements Property {
      */
     protected Serializable getValueDeprecation() {
         if (isDeprecated()) {
+            Optional<Property> deprecatedFallback = getDeprecatedFallback();
             // Check if we need to log deprecation message
             if (log.isWarnEnabled()) {
                 StringBuilder msg = newDeprecatedMessage();
-                if (deprecatedFallback == null) {
-                    msg.append("Return value from deprecated property");
-                } else {
-                    msg.append("Return value from '").append(deprecatedFallback.getXPath()).append(
+                if (deprecatedFallback.isPresent()) {
+                    msg.append("Return value from '").append(deprecatedFallback.get().getXPath()).append(
                             "' if not null, from deprecated property otherwise");
+                } else {
+                    msg.append("Return value from deprecated property");
                 }
                 if (log.isTraceEnabled()) {
                     log.warn(msg, new NuxeoException());
@@ -504,9 +500,7 @@ public abstract class AbstractProperty implements Property {
                     log.warn(msg);
                 }
             }
-            if (deprecatedFallback != null) {
-                return deprecatedFallback.getValue();
-            }
+            return deprecatedFallback.map(Property::getValue).orElse(null);
         }
         return null;
     }
diff --git a/nuxeo-core/nuxeo-core-api/src/main/java/org/nuxeo/ecm/core/api/model/impl/PropertyFactory.java b/nuxeo-core/nuxeo-core-api/src/main/java/org/nuxeo/ecm/core/api/model/impl/PropertyFactory.java
index ffddaf26671..3100957485b 100644
--- a/nuxeo-core/nuxeo-core-api/src/main/java/org/nuxeo/ecm/core/api/model/impl/PropertyFactory.java
+++ b/nuxeo-core/nuxeo-core-api/src/main/java/org/nuxeo/ecm/core/api/model/impl/PropertyFactory.java
@@ -19,8 +19,12 @@
  */
 package org.nuxeo.ecm.core.api.model.impl;
 
+import static org.nuxeo.ecm.core.api.model.impl.AbstractProperty.IS_DEPRECATED;
 import static org.nuxeo.ecm.core.api.model.impl.AbstractProperty.IS_SECURED;
 
+import java.util.stream.IntStream;
+
+import com.sun.xml.xsom.impl.SchemaSetImpl;
 import org.nuxeo.ecm.core.api.model.Property;
 import org.nuxeo.ecm.core.api.model.impl.primitives.BinaryProperty;
 import org.nuxeo.ecm.core.api.model.impl.primitives.BlobProperty;
@@ -31,10 +35,11 @@ import org.nuxeo.ecm.core.api.model.impl.primitives.ExternalBlobProperty;
 import org.nuxeo.ecm.core.api.model.impl.primitives.LongProperty;
 import org.nuxeo.ecm.core.api.model.impl.primitives.StringProperty;
 import org.nuxeo.ecm.core.schema.PropertyCharacteristicHandler;
+import org.nuxeo.ecm.core.schema.PropertyDeprecationHandler;
+import org.nuxeo.ecm.core.schema.SchemaManager;
 import org.nuxeo.ecm.core.schema.TypeConstants;
 import org.nuxeo.ecm.core.schema.types.Field;
 import org.nuxeo.ecm.core.schema.types.ListType;
-import org.nuxeo.ecm.core.schema.types.Schema;
 import org.nuxeo.ecm.core.schema.types.SimpleTypeImpl;
 import org.nuxeo.ecm.core.schema.types.Type;
 import org.nuxeo.ecm.core.schema.types.primitives.BinaryType;
@@ -55,28 +60,8 @@ public class PropertyFactory {
         // utility class
     }
 
-    public static Property createProperty(Property parent, Field field, int f) {
-        int flags = f;
-        // check if property to create is a secured one
-        if (parent instanceof AbstractProperty) { // should always be the case
-            if (((AbstractProperty) parent).areFlagsSet(IS_SECURED)) {
-                flags |= IS_SECURED;
-            } else if ((flags & IS_SECURED) == 0) {
-                Schema schema = parent.getSchema();
-                StringBuilder xpath = new StringBuilder();
-                if (parent.getParent() != null) {
-                    xpath.append(parent.getXPath()).append('/');
-                }
-                xpath.append(field.getName().getLocalName());
-
-                PropertyCharacteristicHandler propertyHandler = Framework.getService(
-                        PropertyCharacteristicHandler.class);
-                if (propertyHandler.isSecured(schema.getName(), xpath.toString())) {
-                    flags |= IS_SECURED;
-                }
-            }
-        }
-
+    public static Property createProperty(Property parent, Field field, int flags) {
+        flags = computePropertyFlags(parent, field, flags);
         Type type = field.getType();
         if (type instanceof SimpleTypeImpl) {
             // type with constraint
@@ -116,4 +101,33 @@ public class PropertyFactory {
         }
     }
 
+    protected static int computePropertyFlags(Property parent, Field field, int flags) {
+        // check if property to create has flags to inherit from parent or configuration
+        if (parent instanceof AbstractProperty) { // should always be the case
+            // compute inherit flags from parent
+            flags |= ((AbstractProperty) parent).areFlagsSet(IS_SECURED) ? IS_SECURED : 0;
+            flags |= ((AbstractProperty) parent).areFlagsSet(IS_DEPRECATED) ? IS_DEPRECATED : 0;
+            // if parent is not secured or deprecated, compute characteristics for current property
+            if ((flags & IS_SECURED) == 0 || (flags & IS_DEPRECATED) == 0) {
+                String schemaName = parent.getSchema().getName();
+                StringBuilder xpathBuilder = new StringBuilder();
+                if (parent.getParent() != null) {
+                    xpathBuilder.append(parent.getXPath()).append('/');
+                }
+                xpathBuilder.append(field.getName().getLocalName());
+                String xpath = xpathBuilder.toString();
+
+                SchemaManager schemaManager = Framework.getService(SchemaManager.class);
+                if ((flags & IS_SECURED) == 0 && schemaManager.isSecured(schemaName, xpath)) {
+                    flags |= IS_SECURED;
+                }
+                PropertyDeprecationHandler deprecatedProperties = schemaManager.getDeprecatedProperties();
+                if ((flags & IS_DEPRECATED) == 0 && deprecatedProperties.isMarked(schemaName, xpath)) {
+                    flags |= IS_DEPRECATED;
+                }
+            }
+        }
+        return flags;
+    }
+
 }
