diff --git a/tests/test_model.py b/tests/test_model.py
index 37c6bb87374b24df99537abda6b43e54de8a55f3..d9a8f770a4b8d809cdfb2a315ba3f7d8377cd95d 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -177,14 +177,8 @@ def test_schema(data_model):
     assert lj.config == ca.config == cha.config == (not ll.config) == True
     assert la.ns == ld.ns
     assert lc.ns == "testb"
-    assert la.default_value() == 11
-    assert ld.default_value() == 199
     assert ld.type.default == 111
-    assert lla.default_value() == ArrayValue([42, 54])
     assert lla.type.default == 11
-    assert lo.default_value() == True
-    assert lp.default_value() == 42
-    assert lsta.default_value() == ObjectValue()
     assert la.type.parse_value("99") == 99
     with pytest.raises(YangTypeError):
         ld.type.parse_value("99")
diff --git a/yangson/instance.py b/yangson/instance.py
index a9053a81b1cec2b5df99a76f0053d9cba34cb1c0..39c629078cead0c2185493ec6e14d038b52418b2 100644
--- a/yangson/instance.py
+++ b/yangson/instance.py
@@ -97,7 +97,7 @@ class InstanceNode:
 
     def put_member(self, name: InstanceName, value: Value,
                    raw: bool = False) -> "InstanceNode":
-        """Return a copy of the receiver with a new value of a member.
+        """Return receiver's member with a new value.
 
         If the member is permitted by the schema but doesn't exist, it
         is created.
@@ -118,7 +118,7 @@ class InstanceNode:
         newval = self.value.copy()
         newval[name] = csn.from_raw(value) if raw else value
         ts = datetime.now()
-        return self._copy(ObjectValue(newval, ts) , ts)
+        return self._copy(ObjectValue(newval, ts) , ts).member(name)
 
     def delete_member(self, name: InstanceName) -> "InstanceNode":
         """Return a copy of the receiver with a member deleted from its value.
@@ -294,31 +294,6 @@ class InstanceNode:
         """
         self.schema_node.validate(self, ctype)
 
-    def add_defaults(self) -> "InstanceNode":
-        """Return a copy of the receiver with defaults added to its value."""
-        sn = self.schema_node
-        if isinstance(self.value, ArrayValue) and isinstance(sn, ListNode):
-            try:
-                inst = self.entry(0)
-            except NonexistentInstance:
-                return self
-            try:
-                while True:
-                    ninst = inst.add_defaults()
-                    inst = ninst.next()
-            except NonexistentInstance:
-                return ninst.up()
-        if isinstance(sn, InternalNode):
-            res = self
-            if self.value:
-                for mn in self.value:
-                    m = res.member(mn) if res is self else res.sibling(mn)
-                    res = m.add_defaults()
-                res = res.up()
-            sn._apply_defaults(res.value)
-            return res
-        return self
-
     def raw_value(self) -> RawValue:
         """Return receiver's value in a raw form (ready for JSON encoding)."""
         if isinstance(self.value, ObjectValue):
@@ -338,6 +313,25 @@ class InstanceNode:
             res = self.schema_node.type.to_raw(self.value)
         return res
 
+    def add_defaults(self, ctype: ContentType = None) -> "InstanceNode":
+        """Return the receiver with defaults added recursively to its value.
+
+        Args:
+            ctype: Content type of the defaults to be added. If it is
+                ``None``, the content type will be the same as receiver's.
+        """
+        sn = self.schema_node
+        val = self.value
+        if not (isinstance(val, ObjectValue) and isinstance(sn, InternalNode)):
+            return self
+        res = self
+        if val:
+            for mn in val:
+                m = res.member(mn) if res is self else res.sibling(mn)
+                res = m.add_defaults(ctype)
+            res = res.up()
+        return sn._add_defaults(res, ctype)
+
     def _peek_schema_route(self, sroute: SchemaRoute) -> Value:
         irt = InstanceRoute()
         sn = self.schema_node
@@ -363,8 +357,8 @@ class InstanceNode:
             return [ self.entry(i) for i in range(len(val)) ]
         return [self]
 
-    def _children(self,
-                 qname: Union[QualName, bool] = None) -> List["InstanceNode"]:
+    def _children(self, qname:
+                  Union[QualName, bool] = None) -> List["InstanceNode"]:
         """XPath - return the list of receiver's children."""
         sn = self.schema_node
         if not isinstance(sn, InternalNode): return []
@@ -374,31 +368,20 @@ class InstanceNode:
             iname = cn.iname()
             if iname in self.value:
                 return self.member(iname)._node_set()
-            res = cn._default_nodes(self)
-            if not res: return res
+            wd = cn._default_instance(self, ContentType.all, lazy=True)
+            if iname not in wd.value: return []
             while True:
                 cn = cn.parent
-                if cn is sn: return res
-                if ((cn.when is None or cn.when.evaluate(self)) and
-                    (not isinstance(cn, CaseNode) or
-                     cn.qual_name == cn.parent.default_case)):
-                    continue
-                return []
+                if cn is sn:
+                    return wd.member(iname)._node_set()
+                if (cn.when and not cn.when.evaluate(self) or
+                    isinstance(cn, CaseNode) and
+                    cn.qual_name != cn.parent.default_case):
+                    return []
         res = []
-        for cn in sn.children:
-            if isinstance(cn, ChoiceNode):
-                cin = cn._child_inst_names().intersection(self.value)
-                if cin:
-                    for i in cin:
-                        res.extend(self.member(i)._node_set())
-                else:
-                    res.extend(cn._default_nodes(inst))
-            else:
-                iname = cn.iname()
-                if iname in self.value:
-                    res.extend(self.member(iname)._node_set())
-                else:
-                    res.extend(cn._default_nodes(self))
+        wd = sn._add_defaults(self, ContentType.all, lazy=True)
+        for mn in wd.value:
+            res.extend(wd.member(mn)._node_set())
         return res
 
     def _descendants(self, qname: Union[QualName, bool] = None,
diff --git a/yangson/schema.py b/yangson/schema.py
index 7fb3b061d467e66c2271049ea032e8723f90d993..10c940dab8574f16dabb9f9fcf2150067796f176 100644
--- a/yangson/schema.py
+++ b/yangson/schema.py
@@ -70,15 +70,15 @@ class SchemaNode:
         """Does the receiver (also) represent configuration?"""
         return self.content_type().value & ContentType.config.value != 0
 
-    def content_type(self) -> ContentType:
-        """Receiver's content type."""
-        return self._ctype if self._ctype else self.parent.content_type()
-
     @property
     def mandatory(self) -> bool:
         """Is the receiver a mandatory node?"""
         return False
 
+    def content_type(self) -> ContentType:
+        """Receiver's content type."""
+        return self._ctype if self._ctype else self.parent.content_type()
+
     def data_parent(self) -> Optional["InternalNode"]:
         """Return the closest ancestor data node."""
         parent = self.parent
@@ -122,10 +122,6 @@ class SchemaNode:
         """Return a list of data paths to descendant state data roots."""
         return [r.data_path() for r in self._state_roots()]
 
-    def default_value(self) -> Optional[Value]:
-        """Return default content as defined by the receiver and descendants."""
-        raise NotImplementedError
-
     def validate(self, inst: "InstanceNode", ctype: ContentType) -> None:
         """Validate instance against the receiver.
 
@@ -259,7 +255,6 @@ class InternalNode(SchemaNode):
         super().__init__()
         self.children = [] # type: List[SchemaNode]
         self._new_ns = None # type: Optional[ModuleId]
-        self.default_children = [] # type: List[SchemaNode]
         self._mandatory_children = set() # type: MutableSet[SchemaNode]
 
     @property
@@ -323,38 +318,16 @@ class InternalNode(SchemaNode):
             res = c.get_data_child(name, ns)
             if res: return res
 
-    def filter_children(self, ctype: ContentType = None,
-                        cnode: "InstanceNode" = None) -> List[SchemaNode]:
-        """Return list of valid children with matching content type.
+    def filter_children(self, ctype: ContentType = None) -> List[SchemaNode]:
+        """Return receiver's children based on content type.
 
         Args:
             ctype: Content type.
-            cnode: Context instance node for evaluating "when" statements.
-                If it is ``None``, "when" conditions are ignored.
         """
         if ctype is None:
-            ctype = (ContentType.nonconfig if
-                     not isinstance(self, InternalNode) else
-                     self.content_type())
-        res = []
-        for child in self.children:
-            if (child.content_type().value & ctype.value == 0 or
-                isinstance(child, (RpcActionNode, NotificationNode))):
-                continue
-            if cnode is None or child.when is None:
-                res.append(child)
-            elif isinstance(child, DataNode):
-                mn = child.iname()
-                dummy = cnode.put_member(mn, (None,))
-                if child.when.evaluate(dummy.member(mn)):
-                    res.append(child)
-            else:
-                dval = cnode.value.copy()
-                for cc in child.data_children():
-                    dval.pop(cc.iname(), None)
-                if child.when.evaluate(cnode.update(dval)):
-                    res.append(child)
-        return res
+            ctype = self.content_type()
+        return [c for c in self.children if
+                c.content_type().value & ctype.value != 0]
 
     def data_children(self) -> List["DataNode"]:
         """Return the set of all data nodes directly under the receiver."""
@@ -366,15 +339,6 @@ class InternalNode(SchemaNode):
                 res.extend(child.data_children())
         return res
 
-    def default_value(self) -> ObjectValue:
-        """Override the superclass method."""
-        res = ObjectValue()
-        for c in self.default_children:
-            dflt = c.default_value()
-            if dflt is not None:
-                res[c.iname()] = dflt
-        return res
-
     def validate(self, inst: "InstanceNode", ctype: ContentType) -> None:
         """Extend the superclass method."""
         if not isinstance(inst.value, ObjectValue):
@@ -442,27 +406,18 @@ class InternalNode(SchemaNode):
         for c in self.children:
             c._post_process()
 
-    def _add_default_child(self, node: SchemaNode) -> None:
-        """Add `node` to the list of default children."""
-        self.default_children.append(node)
-
     def _add_mandatory_child(self, node: SchemaNode) -> None:
         """Add `node` to the set of mandatory children."""
         self._mandatory_children.add(node)
 
-    def _apply_defaults(self, value: ObjectValue) -> None:
-        """Return a copy of `value` with added default contents."""
-        for c in self.default_children:
-            if isinstance(c, ChoiceNode):
-                ac = c.active_case(value)
-                if ac:
-                    ac._apply_defaults(value)
-                elif c.default_case:
-                    value.update(c.get_child(*c.default_case).default_value())
-            else:
-                cn = c.iname()
-                if cn not in value:
-                    value[cn] = c.default_value()
+    def _add_defaults(self, inst: "InstanceNode", ctype: ContentType,
+                      lazy: bool = False) -> "InstanceNode":
+        for c in self.filter_children(ctype):
+            if isinstance(c, DataNode):
+                inst = c._default_instance(inst, ctype, lazy)
+            elif not isinstance(c, (RpcActionNode, NotificationNode)):
+                inst = c._add_defaults(inst, ctype)
+        return inst
 
     def _state_roots(self) -> List[SchemaNode]:
         if self.content_type() == ContentType.nonconfig:
@@ -625,6 +580,17 @@ class DataNode(SchemaNode):
         self._check_must(inst)
         super().validate(inst, ctype)
 
+    def _default_instance(self, pnode: "InstanceNode", ctype: ContentType,
+                          lazy: bool = False) -> "InstanceNode":
+        iname = self.iname()
+        if iname in pnode.value: return pnode
+        nm = pnode.put_member(iname, (None,))
+        if not self.when or self.when.evaluate(nm):
+            wd = self._default_value(nm, ctype, lazy)
+            if wd.value is not None:
+                return wd.up()
+        return pnode
+
     def _check_must(self, inst: "InstanceNode") -> None:
         """Check that all receiver's "must" constraints for the instance.
 
@@ -704,15 +670,9 @@ class TerminalNode(SchemaNode):
             self.type.ref_type = ref.type
 
     def _default_nodes(self, inst: "InstanceNode") -> List["InstanceNode"]:
-        dflt = self.default_value()
-        if dflt is None: return []
-        iname = self.iname()
-        ni = inst.put_member(iname, (None,))
-        res = ni.member(iname)
-        if self.when is None or self.when.evaluate(res):
-            res.value = dflt
-            return res._node_set()
-        return []
+        di = self._default_instance(inst, ContentType.all)
+        return [] if di is None else [self]
+        return inst.put_member(self.iname(), dflt)._node_set()
 
     def _ascii_tree(self, indent: str) -> str:
         return ""
@@ -733,22 +693,25 @@ class ContainerNode(DataNode, InternalNode):
         """Is the receiver a mandatory node?"""
         return not self.presence and super().mandatory
 
-    def _add_default_child(self, node: SchemaNode) -> None:
-        """Extend the superclass method."""
-        if not (self.presence or self.default_children):
-            self.parent._add_default_child(self)
-        super()._add_default_child(node)
-
     def _add_mandatory_child(self, node: SchemaNode):
         if not (self.presence or self.mandatory):
             self.parent._add_mandatory_child(self)
         super()._add_mandatory_child(node)
 
+    def _default_instance(self, pnode: "InstanceNode", ctype: ContentType,
+                          lazy: bool = False) -> "InstanceNode":
+        if self.presence:
+            return pnode
+        return super()._default_instance(pnode, ctype, lazy)
+
+    def _default_value(self, inst: "InstanceNode", ctype: ContentType,
+                       lazy: bool) -> Optional["InstanceNode"]:
+        inst.value = ObjectValue()
+        return inst if lazy else self._add_defaults(inst, ctype)
+
     def _default_nodes(self, inst: "InstanceNode") -> List["InstanceNode"]:
         if self.presence: return []
-        iname = self.iname()
-        ni = inst.put_member(iname, ObjectValue())
-        res = ni.member(iname)
+        res = inst.put_member(self.iname(), ObjectValue())
         if self.when is None or self.when.evaluate(res):
             return [res]
         return []
@@ -894,9 +857,9 @@ class ListNode(SequenceNode, InternalNode):
             except NonexistentInstance:
                 continue
 
-    def _add_default_child(self, node: SchemaNode) -> None:
-        if node.qual_name not in self.keys:
-            super()._add_default_child(node)
+    def _default_instance(self, pnode: "InstanceNode", ctype: ContentType,
+                          lazy: bool = False) -> "InstanceNode":
+        return pnode
 
     def _post_process(self) -> None:
         super()._post_process()
@@ -937,6 +900,19 @@ class ChoiceNode(InternalNode):
         """Is the receiver a mandatory node?"""
         return self._mandatory
 
+    def _add_defaults(self, inst: "InstanceNode",
+                      ctype: ContentType) -> "InstanceNode":
+        if self.when and not self.when.evaluate(inst):
+            return inst
+        ac = self.active_case(inst.value)
+        if ac:
+            return ac._add_defaults(inst, ctype)
+        elif self.default_case:
+            dc = self.get_child(*self.default_case)
+            if not dc.when or dc.when.evaluate(inst):
+                return dc._add_defaults(inst, ctype)
+        return inst
+
     def active_case(self, value: ObjectValue) -> Optional["CaseNode"]:
         """Return receiver's case that's active in an instance node value.
 
@@ -949,11 +925,6 @@ class ChoiceNode(InternalNode):
                     or cc.iname() in value):
                         return case
 
-    def default_value(self) -> Optional[ObjectValue]:
-        """Override the superclass method."""
-        if self.default_case in [c.qual_name for c in self.default_children]:
-            return self.get_child(*self.default_case).default_value()
-
     def _pattern_entry(self) -> SchemaPattern:
         if not self.children:
             return Empty()
@@ -965,12 +936,6 @@ class ChoiceNode(InternalNode):
             prev = SchemaPattern.optional(prev)
         return ConditionalPattern(prev, self.when) if self.when else prev
 
-    def _add_default_child(self, node: "CaseNode") -> None:
-        """Extend the superclass method."""
-        if not (self._mandatory or self.default_children):
-            self.parent._add_default_child(self)
-        super()._add_default_child(node)
-
     def _post_process(self) -> None:
         super()._post_process()
         if self._mandatory:
@@ -1014,12 +979,6 @@ class ChoiceNode(InternalNode):
 class CaseNode(InternalNode):
     """Case node."""
 
-    def _add_default_child(self, node: SchemaNode) -> None:
-        """Extend the superclass method."""
-        if not self.default_children:
-            self.parent._add_default_child(self)
-        super()._add_default_child(node)
-
     def _pattern_entry(self) -> SchemaPattern:
         return super()._schema_pattern()
 
@@ -1041,16 +1000,22 @@ class LeafNode(DataNode, TerminalNode):
         """Is the receiver a mandatory node?"""
         return self._mandatory
 
-    def default_value(self) -> Optional[ScalarValue]:
-        """Override the superclass method."""
-        return self.type.default if self.default is None else self.default
+    def _default_value(self, inst: "InstanceNode", ctype: ContentType,
+                       lazy: bool) -> "InstanceNode":
+        if self.mandatory:
+            inst.value = None
+        elif self.default is not None:
+            inst.value = self.default
+        elif self.type.default is not None:
+            inst.value = self.type.default
+        else:
+            inst.value = None
+        return inst
 
     def _post_process(self) -> None:
         super()._post_process()
         if self._mandatory:
             self.parent._add_mandatory_child(self)
-        elif self.default_value() is not None:
-            self.parent._add_default_child(self)
 
     def _tree_line(self) -> str:
         return super()._tree_line() + ("" if self._mandatory else "?")
@@ -1061,23 +1026,23 @@ class LeafNode(DataNode, TerminalNode):
 class LeafListNode(SequenceNode, TerminalNode):
     """Leaf-list node."""
 
-    def default_value(self) -> Optional[ArrayValue]:
-        """Override the superclass method."""
-        if self.default is not None:
-            return self.default
-        if self.type.default is not None:
-            return ArrayValue([self.type.default])
+    def _default_value(self, inst: "InstanceNode", ctype: ContentType,
+                       lazy: bool) -> "InstanceNode":
+        if self.mandatory:
+            inst.value = None
+        elif self.default is not None:
+            inst.value = self.default
+        elif self.type.default is not None:
+            inst.value = ArrayValue([self.type.default])
+        else:
+            inst.value = None
+        return inst
 
     def _check_unique(self, inst: "InstanceNode") -> None:
         if (self.content_type() == ContentType.config and
             len(set(inst.value)) < len(inst.value)):
             raise SemanticError(inst, "non-unique leaf-list values")
 
-    def _post_process(self) -> None:
-        super()._post_process()
-        if self.min_elements == 0 and self.default_value() is not None:
-            self.parent._add_default_child(self)
-
     def _default_stmt(self, stmt: Statement, mid: ModuleId) -> None:
         val = self.type.parse_value(stmt.argument)
         if self.default is None:
@@ -1116,6 +1081,10 @@ class AnydataNode(DataNode):
             return res
         return convert(rval)
 
+    def _default_instance(self, pnode: "InstanceNode", ctype: ContentType,
+                          lazy: bool = False) -> "InstanceNode":
+        return pnode
+
     def _tree_line(self) -> str:
         return super()._tree_line() + ("" if self._mandatory else "?")
 
@@ -1254,4 +1223,5 @@ class SemanticError(ValidationError):
     pass
 
 from .xpathast import Expr, LocationPath, Step, Root
-from .instance import InstanceNode, ArrayEntry, NonexistentInstance
+from .instance import (InstanceNode, ArrayEntry,
+                       NonexistentInstance, ObjectMember)
diff --git a/yangson/schpattern.py b/yangson/schpattern.py
index f8f0fd58344e2eed3f93490462ff086a279dfadb..9784d55484ca47f6c5e5d8ce5f8c567deff40414 100644
--- a/yangson/schpattern.py
+++ b/yangson/schpattern.py
@@ -125,7 +125,7 @@ class Member(Typeable, Conditional):
     def _eval_when(self, cnode: "InstanceNode") -> None:
         if self.when:
             dummy = cnode.put_member(self.name, (None,))
-            super()._eval_when(dummy.member(self.name))
+            super()._eval_when(dummy)
 
     def nullable(self, ctype: ContentType) -> bool:
         """Override the superclass method."""