diff --git a/db/model/node.go b/db/model/node.go
new file mode 100644
index 0000000..936a79a
--- /dev/null
+++ b/db/model/node.go
@@ -0,0 +1,456 @@
+package model
+
+import (
+	"fmt"
+	"github.com/golang/protobuf/proto"
+	"reflect"
+	"strings"
+)
+
+const (
+	NONE string = "none"
+)
+
+type Node struct {
+	root      *Root
+	Type      interface{}
+	Branches  map[string]*Branch
+	Tags      map[string]*Revision
+	Proxy     *Proxy
+	EventBus  *EventBus
+	AutoPrune bool
+}
+
+func NewNode(root *Root, initialData interface{}, autoPrune bool, txid string) *Node {
+	cn := &Node{}
+
+	cn.root = root
+	cn.Branches = make(map[string]*Branch)
+	cn.Tags = make(map[string]*Revision)
+	cn.Proxy = nil
+	cn.EventBus = nil
+	cn.AutoPrune = autoPrune
+
+	if IsProtoMessage(initialData) {
+		cn.Type = reflect.ValueOf(initialData).Interface()
+		dataCopy := proto.Clone(initialData.(proto.Message))
+		cn.initialize(dataCopy, txid)
+	} else if reflect.ValueOf(initialData).IsValid() {
+		cn.Type = reflect.ValueOf(initialData).Interface()
+	} else {
+		// not implemented error
+		fmt.Errorf("cannot process initial data - %+v", initialData)
+	}
+
+	return cn
+}
+
+func (cn *Node) makeNode(data interface{}, txid string) *Node {
+	return NewNode(cn.root, data, true, txid)
+}
+
+func (cn *Node) makeRevision(branch *Branch, data interface{}, children map[string][]*Revision) *Revision {
+	return cn.root.makeRevision(branch, data, children)
+}
+
+func (cn *Node) makeLatest(branch *Branch, revision *Revision, changeAnnouncement map[string]interface{}) {
+	if _, ok := branch.revisions[revision.Hash]; !ok {
+		branch.revisions[revision.Hash] = revision
+	}
+
+	if branch.Latest == nil || revision.Hash != branch.Latest.Hash {
+		branch.Latest = revision
+	}
+
+	if changeAnnouncement != nil && branch.Txid == "" {
+		if cn.Proxy != nil {
+			for changeType, data := range changeAnnouncement {
+				// TODO: Invoke callback
+				fmt.Printf("invoking callback - changeType: %+v, data:%+v\n", changeType, data)
+			}
+		}
+
+		for changeType, data := range changeAnnouncement {
+			// TODO: send notifications
+			fmt.Printf("sending notification - changeType: %+v, data:%+v\n", changeType, data)
+		}
+	}
+}
+
+func (cn *Node) Latest() *Revision {
+	if branch, exists := cn.Branches[NONE]; exists {
+		return branch.Latest
+	}
+	return nil
+}
+
+func (cn *Node) GetHash(hash string) *Revision {
+	return cn.Branches[NONE].revisions[hash]
+}
+
+func (cn *Node) initialize(data interface{}, txid string) {
+	var children map[string][]*Revision
+	children = make(map[string][]*Revision)
+	for fieldName, field := range ChildrenFields(cn.Type) {
+		fieldValue := GetAttributeValue(data, fieldName, 0)
+
+		if fieldValue.IsValid() {
+			if field.IsContainer {
+				if field.Key != "" {
+					var keysSeen []string
+
+					for i := 0; i < fieldValue.Len(); i++ {
+						v := fieldValue.Index(i)
+						rev := cn.makeNode(v.Interface(), txid).Latest()
+						key := GetAttributeValue(v.Interface(), field.Key, 0)
+						for _, k := range keysSeen {
+							if k == key.String() {
+								fmt.Errorf("duplicate key - %s", k)
+							}
+						}
+						children[fieldName] = append(children[fieldName], rev)
+						keysSeen = append(keysSeen, key.String())
+					}
+
+				} else {
+					for i := 0; i < fieldValue.Len(); i++ {
+						v := fieldValue.Index(i)
+						children[fieldName] = append(children[fieldName], cn.makeNode(v.Interface(), txid).Latest())
+					}
+				}
+			} else {
+				children[fieldName] = append(children[fieldName], cn.makeNode(fieldValue.Interface(), txid).Latest())
+			}
+		} else {
+			fmt.Errorf("field is invalid - %+v", fieldValue)
+		}
+	}
+	// FIXME: ClearField???  No such method in go protos.  Reset?
+	//data.ClearField(field_name)
+	branch := NewBranch(cn, "", nil, cn.AutoPrune)
+	rev := cn.makeRevision(branch, data, children)
+	cn.makeLatest(branch, rev, nil)
+	cn.Branches[txid] = branch
+}
+
+func (cn *Node) makeTxBranch(txid string) *Branch {
+	branchPoint := cn.Branches[NONE].Latest
+	branch := NewBranch(cn, txid, branchPoint, true)
+	cn.Branches[txid] = branch
+	return branch
+}
+
+func (cn *Node) deleteTxBranch(txid string) {
+	delete(cn.Branches, txid)
+}
+
+type t_makeBranch func(*Node) *Branch
+
+//
+// Get operation
+//
+func (cn *Node) Get(path string, hash string, depth int, deep bool, txid string) interface{} {
+	if deep {
+		depth = -1
+	}
+
+	for strings.HasPrefix(path, "/") {
+		path = path[1:]
+	}
+
+	var branch *Branch
+	var rev *Revision
+
+	// FIXME: should empty txid be cleaned up?
+	if branch = cn.Branches[txid]; txid == "" || branch == nil {
+		branch = cn.Branches[NONE]
+	}
+
+	if hash != "" {
+		rev = branch.revisions[hash]
+	} else {
+		rev = branch.Latest
+	}
+
+	return cn.get(rev, path, depth)
+}
+
+func (cn *Node) findRevByKey(revs []*Revision, keyName string, value string) (int, *Revision) {
+	for i, rev := range revs {
+		dataValue := reflect.ValueOf(rev.Config.Data)
+		dataStruct := GetAttributeStructure(rev.Config.Data, keyName, 0)
+
+		fieldValue := dataValue.Elem().FieldByName(dataStruct.Name)
+
+		if fieldValue.Interface().(string) == value {
+			return i, rev
+		}
+	}
+
+	fmt.Errorf("key %s=%s not found", keyName, value)
+
+	return -1, nil
+}
+
+func (cn *Node) get(rev *Revision, path string, depth int) interface{} {
+	if path == "" {
+		return cn.doGet(rev, depth)
+	}
+
+	partition := strings.SplitN(path, "/", 2)
+	name := partition[0]
+	path = partition[1]
+
+	field := ChildrenFields(cn.Type)[name]
+
+	if field.IsContainer {
+		if field.Key != "" {
+			children := rev.Children[name]
+			if path != "" {
+				partition = strings.SplitN(path, "/", 2)
+				key := partition[0]
+				path = ""
+				key = field.KeyFromStr(key).(string)
+				_, childRev := cn.findRevByKey(children, field.Key, key)
+				childNode := childRev.getNode()
+				return childNode.get(childRev, path, depth)
+			} else {
+				var response []interface{}
+				for _, childRev := range children {
+					childNode := childRev.getNode()
+					value := childNode.doGet(childRev, depth)
+					response = append(response, value)
+				}
+				return response
+			}
+		} else {
+			childRev := rev.Children[name][0]
+			childNode := childRev.getNode()
+			return childNode.get(childRev, path, depth)
+		}
+	}
+	return nil
+}
+
+func (cn *Node) doGet(rev *Revision, depth int) interface{} {
+	msg := rev.Get(depth)
+
+	if cn.Proxy != nil {
+		// TODO: invoke GET callback
+		fmt.Println("invoking proxy GET Callbacks")
+	}
+	return msg
+}
+
+//
+// Update operation
+//
+func (n *Node) Update(path string, data interface{}, strict bool, txid string, makeBranch t_makeBranch) *Revision {
+	// FIXME: is this required ... a bit overkill to take out a "/"
+	for strings.HasPrefix(path, "/") {
+		path = path[1:]
+	}
+
+	var branch *Branch
+	var ok bool
+	if branch, ok = n.Branches[txid]; !ok {
+		branch = makeBranch(n)
+	}
+
+	if path == "" {
+		return n.doUpdate(branch, data, strict)
+	}
+	return &Revision{}
+}
+
+func (n *Node) doUpdate(branch *Branch, data interface{}, strict bool) *Revision {
+	if reflect.TypeOf(data) != n.Type {
+		// TODO raise error
+		fmt.Errorf("data does not match type: %+v", n.Type)
+	}
+
+	// TODO: noChildren?
+
+	if n.Proxy != nil {
+		// TODO: n.proxy.InvokeCallbacks(CallbackType.PRE_UPDATE, data)
+		fmt.Println("invoking proxy PRE_UPDATE Callbacks")
+	}
+	if branch.Latest.getData() != data {
+		if strict {
+			// TODO: checkAccessViolations(data, branch.GetLatest.data)
+			fmt.Println("checking access violations")
+		}
+		rev := branch.Latest.UpdateData(data, branch)
+		n.makeLatest(branch, rev, nil) // TODO -> changeAnnouncement needs to be a tuple (CallbackType.POST_UPDATE, rev.data)
+		return rev
+	} else {
+		return branch.Latest
+	}
+}
+
+// TODO: the python implementation has a method to check if the data has no children
+//func (n *SomeNode) noChildren(data interface{}) bool {
+//	for fieldName, field := range ChildrenFields(n.Type) {
+//		fieldValue := GetAttributeValue(data, fieldName)
+//
+//		if fieldValue.IsValid() {
+//			if field.IsContainer {
+//				if len(fieldValue) > 0 {
+//
+//				}
+//			} else {
+//
+//			}
+//
+//		}
+//	}
+//}
+
+//
+// Add operation
+//
+func (n *Node) Add(path string, data interface{}, txid string, makeBranch t_makeBranch) *Revision {
+	for strings.HasPrefix(path, "/") {
+		path = path[1:]
+	}
+	if path == "" {
+		// TODO raise error
+		fmt.Errorf("cannot add for non-container mode\n")
+	}
+
+	var branch *Branch
+	var ok bool
+	if branch, ok = n.Branches[txid]; !ok {
+		branch = makeBranch(n)
+	}
+
+	rev := branch.Latest
+
+	partition := strings.SplitN(path, "/", 2)
+	name := partition[0]
+	path = partition[1]
+
+	field := ChildrenFields(n.Type)[name]
+	var children []*Revision
+
+	if field.IsContainer {
+		if path == "" {
+			if field.Key != "" {
+				if n.Proxy != nil {
+					// TODO -> n.proxy.InvokeCallbacks(PRE_ADD, data)
+					fmt.Println("invoking proxy PRE_ADD Callbacks")
+				}
+
+				copy(children, rev.Children[name])
+				key := GetAttributeValue(data, field.Key, 0)
+				if _, rev := n.findRevByKey(children, field.Key, key.String()); rev != nil {
+					// TODO raise error
+					fmt.Errorf("duplicate key found: %s", key.String())
+				}
+
+				childRev := n.makeNode(data, "").Latest()
+				children = append(children, childRev)
+				rev := rev.UpdateChildren(name, children, branch)
+				n.makeLatest(branch, rev, nil) // TODO -> changeAnnouncement needs to be a tuple (CallbackType.POST_ADD, rev.data)
+				return rev
+			} else {
+				fmt.Errorf("cannot add to non-keyed container\n")
+			}
+		} else if field.Key != "" {
+			partition := strings.SplitN(path, "/", 2)
+			key := partition[0]
+			path = partition[1]
+			key = field.KeyFromStr(key).(string)
+			copy(children, rev.Children[name])
+			idx, childRev := n.findRevByKey(children, field.Key, key)
+			childNode := childRev.getNode()
+			newChildRev := childNode.Add(path, data, txid, makeBranch)
+			children[idx] = newChildRev
+			rev := rev.UpdateChildren(name, children, branch)
+			n.makeLatest(branch, rev, nil)
+			return rev
+		} else {
+			fmt.Errorf("cannot add to non-keyed container\n")
+		}
+	} else {
+		fmt.Errorf("cannot add to non-container field\n")
+	}
+	return nil
+}
+
+//
+// Remove operation
+//
+func (n *Node) Remove(path string, txid string, makeBranch t_makeBranch) *Revision {
+	for strings.HasPrefix(path, "/") {
+		path = path[1:]
+	}
+	if path == "" {
+		// TODO raise error
+		fmt.Errorf("cannot remove for non-container mode\n")
+	}
+	var branch *Branch
+	var ok bool
+	if branch, ok = n.Branches[txid]; !ok {
+		branch = makeBranch(n)
+	}
+
+	rev := branch.Latest
+
+	partition := strings.SplitN(path, "/", 2)
+	name := partition[0]
+	path = partition[1]
+
+	field := ChildrenFields(n.Type)[name]
+	var children []*Revision
+	post_anno := make(map[string]interface{})
+
+	if field.IsContainer {
+		if path == "" {
+			fmt.Errorf("cannot remove without a key\n")
+		} else if field.Key != "" {
+			partition := strings.SplitN(path, "/", 2)
+			key := partition[0]
+			path = partition[1]
+			key = field.KeyFromStr(key).(string)
+			if path != "" {
+				copy(children, rev.Children[name])
+				idx, childRev := n.findRevByKey(children, field.Key, key)
+				childNode := childRev.getNode()
+				newChildRev := childNode.Remove(path, txid, makeBranch)
+				children[idx] = newChildRev
+				rev := rev.UpdateChildren(name, children, branch)
+				n.makeLatest(branch, rev, nil)
+				return rev
+			} else {
+				copy(children, rev.Children[name])
+				idx, childRev := n.findRevByKey(children, field.Key, key)
+				if n.Proxy != nil {
+					data := childRev.getData()
+					fmt.Println("invoking proxy PRE_REMOVE Callbacks")
+					fmt.Printf("setting POST_REMOVE Callbacks : %+v\n", data)
+				} else {
+					fmt.Println("setting POST_REMOVE Callbacks")
+				}
+				children = append(children[:idx], children[idx+1:]...)
+				rev := rev.UpdateChildren(name, children, branch)
+				n.makeLatest(branch, rev, post_anno)
+				return rev
+			}
+		} else {
+			fmt.Errorf("cannot add to non-keyed container\n")
+		}
+	} else {
+		fmt.Errorf("cannot add to non-container field\n")
+	}
+
+	return nil
+}
+
+func (n *Node) LoadLatest(kvStore *Backend, hash string) {
+	branch := NewBranch(n, "", nil, n.AutoPrune)
+	pr := &PersistedRevision{}
+	rev := pr.load(branch, kvStore, n.Type, hash)
+	n.makeLatest(branch, rev.Revision, nil)
+	n.Branches[NONE] = branch
+}
