diff --git a/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java b/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
index 0e3c8ea..7b6ae55 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
@@ -1,4 +1,4 @@
- /*
+/*
  * Copyright 2014-present Open Networking Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,32 +16,29 @@
 package org.onosproject.store.flow.impl;
 
 import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import com.google.common.collect.Streams;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Modified;
-import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.util.KryoNamespace;
 import org.onlab.util.Tools;
-import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.core.CoreService;
@@ -67,42 +64,27 @@
 import org.onosproject.net.flow.FlowRuleStoreDelegate;
 import org.onosproject.net.flow.StoredFlowEntry;
 import org.onosproject.net.flow.TableStatisticsEntry;
-import org.onosproject.persistence.PersistenceService;
 import org.onosproject.store.AbstractStore;
 import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
-import org.onosproject.store.cluster.messaging.ClusterMessage;
-import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
-import org.onosproject.store.flow.ReplicaInfoEvent;
-import org.onosproject.store.flow.ReplicaInfoEventListener;
-import org.onosproject.store.flow.ReplicaInfoService;
+import org.onosproject.store.cluster.messaging.MessageSubject;
 import org.onosproject.store.impl.MastershipBasedTimestamp;
 import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.DocumentPath;
+import org.onosproject.store.service.DocumentTree;
 import org.onosproject.store.service.EventuallyConsistentMap;
 import org.onosproject.store.service.EventuallyConsistentMapEvent;
 import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.NoSuchDocumentPathException;
 import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageException;
 import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.Versioned;
 import org.onosproject.store.service.WallClockTimestamp;
-import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.Futures;
-
-import static com.google.common.base.Strings.isNullOrEmpty;
-import static org.onlab.util.Tools.get;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
-import static org.onosproject.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED;
-import static org.onosproject.store.flow.impl.FlowStoreMessageSubjects.APPLY_BATCH_FLOWS;
-import static org.onosproject.store.flow.impl.FlowStoreMessageSubjects.FLOW_TABLE_BACKUP;
-import static org.onosproject.store.flow.impl.FlowStoreMessageSubjects.GET_DEVICE_FLOW_ENTRIES;
-import static org.onosproject.store.flow.impl.FlowStoreMessageSubjects.GET_FLOW_ENTRY;
-import static org.onosproject.store.flow.impl.FlowStoreMessageSubjects.REMOTE_APPLY_COMPLETED;
-import static org.onosproject.store.flow.impl.FlowStoreMessageSubjects.REMOVE_FLOW_ENTRY;
+import static org.onosproject.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -116,39 +98,23 @@
 
     private final Logger log = getLogger(getClass());
 
+    // Constant exception used to indicate an atomic read-modify-write operation needs to be retried.
+    // We don't want to populate a stack trace every time an optimistic lock is retried.
+    private static final StorageException.ConcurrentModification RETRY;
+
+    // Initialize retry exception with an empty stack trace.
+    static {
+        RETRY = new StorageException.ConcurrentModification();
+        RETRY.setStackTrace(new StackTraceElement[0]);
+    }
+
     private static final int MESSAGE_HANDLER_THREAD_POOL_SIZE = 8;
-    private static final int DEFAULT_MAX_BACKUP_COUNT = 2;
-    private static final boolean DEFAULT_PERSISTENCE_ENABLED = false;
-    private static final int DEFAULT_BACKUP_PERIOD_MILLIS = 2000;
-    private static final long FLOW_RULE_STORE_TIMEOUT_MILLIS = 5000;
-    // number of devices whose flow entries will be backed up in one communication round
-    private static final int FLOW_TABLE_BACKUP_BATCH_SIZE = 1;
+    private static final int MAX_RETRY_DELAY_MILLIS = 50;
 
-    @Property(name = "msgHandlerPoolSize", intValue = MESSAGE_HANDLER_THREAD_POOL_SIZE,
-            label = "Number of threads in the message handler pool")
-    private int msgHandlerPoolSize = MESSAGE_HANDLER_THREAD_POOL_SIZE;
+    private static final String FLOW_TABLE = "onos-flow-table";
 
-    @Property(name = "backupPeriod", intValue = DEFAULT_BACKUP_PERIOD_MILLIS,
-            label = "Delay in ms between successive backup runs")
-    private int backupPeriod = DEFAULT_BACKUP_PERIOD_MILLIS;
-    @Property(name = "persistenceEnabled", boolValue = false,
-            label = "Indicates whether or not changes in the flow table should be persisted to disk.")
-    private boolean persistenceEnabled = DEFAULT_PERSISTENCE_ENABLED;
-
-    @Property(name = "backupCount", intValue = DEFAULT_MAX_BACKUP_COUNT,
-            label = "Max number of backup copies for each device")
-    private volatile int backupCount = DEFAULT_MAX_BACKUP_COUNT;
-
-    private InternalFlowTable flowTable = new InternalFlowTable();
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ReplicaInfoService replicaInfoManager;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ClusterCommunicationService clusterCommunicator;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ClusterService clusterService;
+    private static final MessageSubject APPLY_FLOWS = new MessageSubject("onos-flow-apply");
+    private static final MessageSubject COMPLETE_BATCH = new MessageSubject("onos-flow-batch-complete");
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
@@ -157,25 +123,13 @@
     protected CoreService coreService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ComponentConfigService configService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected MastershipService mastershipService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected PersistenceService persistenceService;
+    protected ClusterCommunicationService clusterCommunicator;
 
-    private Map<Long, NodeId> pendingResponses = Maps.newConcurrentMap();
-    private ExecutorService messageHandlingExecutor;
-    private ExecutorService eventHandler;
-
-    private ScheduledFuture<?> backupTask;
-    private final ScheduledExecutorService backupSenderExecutor =
-            Executors.newSingleThreadScheduledExecutor(groupedThreads("onos/flow", "backup-sender", log));
-
-    private EventuallyConsistentMap<DeviceId, List<TableStatisticsEntry>> deviceTableStats;
-    private final EventuallyConsistentMapListener<DeviceId, List<TableStatisticsEntry>> tableStatsListener =
-            new InternalTableStatsListener();
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ClusterService clusterService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected StorageService storageService;
@@ -186,31 +140,26 @@
             .register(KryoNamespaces.API)
             .register(MastershipBasedTimestamp.class);
 
+    private EventuallyConsistentMap<DeviceId, List<TableStatisticsEntry>> deviceTableStats;
+    private final EventuallyConsistentMapListener<DeviceId, List<TableStatisticsEntry>> tableStatsListener =
+            new InternalTableStatsListener();
 
+    private Set<Long> pendingBatches = Sets.newConcurrentHashSet();
+    private ExecutorService messageHandlingExecutor;
+
+    private DocumentTree<Map<StoredFlowEntry, StoredFlowEntry>> flows;
     private IdGenerator idGenerator;
     private NodeId local;
 
     @Activate
-    public void activate(ComponentContext context) {
-        configService.registerProperties(getClass());
-
+    public void activate() {
         idGenerator = coreService.getIdGenerator(FlowRuleService.FLOW_OP_TOPIC);
 
         local = clusterService.getLocalNode().id();
 
-        eventHandler = Executors.newSingleThreadExecutor(
-                groupedThreads("onos/flow", "event-handler", log));
         messageHandlingExecutor = Executors.newFixedThreadPool(
-                msgHandlerPoolSize, groupedThreads("onos/store/flow", "message-handlers", log));
-
-        registerMessageHandlers(messageHandlingExecutor);
-
-        replicaInfoManager.addListener(flowTable);
-        backupTask = backupSenderExecutor.scheduleWithFixedDelay(
-                flowTable::backup,
-                0,
-                backupPeriod,
-                TimeUnit.MILLISECONDS);
+                MESSAGE_HANDLER_THREAD_POOL_SIZE,
+                groupedThreads("onos/store/flow", "message-handlers", log));
 
         deviceTableStats = storageService.<DeviceId, List<TableStatisticsEntry>>eventuallyConsistentMapBuilder()
                 .withName("onos-flow-table-stats")
@@ -221,110 +170,91 @@
                 .build();
         deviceTableStats.addListener(tableStatsListener);
 
-        logConfig("Started");
+        flows = storageService.<Map<StoredFlowEntry, StoredFlowEntry>>documentTreeBuilder()
+                .withName(FLOW_TABLE)
+                .withSerializer(serializer)
+                .buildDocumentTree()
+                .asDocumentTree();
+
+        clusterCommunicator.addSubscriber(
+                APPLY_FLOWS,
+                serializer::decode,
+                this::applyFlows,
+                messageHandlingExecutor);
+        clusterCommunicator.addSubscriber(
+                COMPLETE_BATCH,
+                serializer::decode,
+                this::completeBatch,
+                messageHandlingExecutor);
+
+        log.info("Started");
     }
 
     @Deactivate
-    public void deactivate(ComponentContext context) {
-        replicaInfoManager.removeListener(flowTable);
-        backupTask.cancel(true);
-        configService.unregisterProperties(getClass(), false);
-        unregisterMessageHandlers();
+    public void deactivate() {
         deviceTableStats.removeListener(tableStatsListener);
         deviceTableStats.destroy();
-        eventHandler.shutdownNow();
+        clusterCommunicator.removeSubscriber(APPLY_FLOWS);
+        clusterCommunicator.removeSubscriber(COMPLETE_BATCH);
         messageHandlingExecutor.shutdownNow();
-        backupSenderExecutor.shutdownNow();
         log.info("Stopped");
     }
 
-    @SuppressWarnings("rawtypes")
-    @Modified
-    public void modified(ComponentContext context) {
-        if (context == null) {
-            logConfig("Default config");
-            return;
-        }
-
-        Dictionary properties = context.getProperties();
-        int newPoolSize;
-        int newBackupPeriod;
-        int newBackupCount;
-        try {
-            String s = get(properties, "msgHandlerPoolSize");
-            newPoolSize = isNullOrEmpty(s) ? msgHandlerPoolSize : Integer.parseInt(s.trim());
-
-            s = get(properties, "backupPeriod");
-            newBackupPeriod = isNullOrEmpty(s) ? backupPeriod : Integer.parseInt(s.trim());
-
-            s = get(properties, "backupCount");
-            newBackupCount = isNullOrEmpty(s) ? backupCount : Integer.parseInt(s.trim());
-        } catch (NumberFormatException | ClassCastException e) {
-            newPoolSize = MESSAGE_HANDLER_THREAD_POOL_SIZE;
-            newBackupPeriod = DEFAULT_BACKUP_PERIOD_MILLIS;
-            newBackupCount = DEFAULT_MAX_BACKUP_COUNT;
-        }
-
-        boolean restartBackupTask = false;
-
-        if (newBackupPeriod != backupPeriod) {
-            backupPeriod = newBackupPeriod;
-            restartBackupTask = true;
-        }
-        if (restartBackupTask) {
-            if (backupTask != null) {
-                // cancel previously running task
-                backupTask.cancel(false);
-            }
-            backupTask = backupSenderExecutor.scheduleWithFixedDelay(
-                    flowTable::backup,
-                    0,
-                    backupPeriod,
-                    TimeUnit.MILLISECONDS);
-        }
-        if (newPoolSize != msgHandlerPoolSize) {
-            msgHandlerPoolSize = newPoolSize;
-            ExecutorService oldMsgHandler = messageHandlingExecutor;
-            messageHandlingExecutor = Executors.newFixedThreadPool(
-                    msgHandlerPoolSize, groupedThreads("onos/store/flow", "message-handlers", log));
-
-            // replace previously registered handlers.
-            registerMessageHandlers(messageHandlingExecutor);
-            oldMsgHandler.shutdown();
-        }
-        if (backupCount != newBackupCount) {
-            backupCount = newBackupCount;
-        }
-        logConfig("Reconfigured");
+    /**
+     * Retries the given supplier until successful.
+     * <p>
+     * This method retries the given supplier until no {@code ConcurrentModification} exceptions are thrown. In
+     * between retries, it waits a semi-random interval to attempt to avoid transaction conflicts with other processes.
+     *
+     * @param supplier the supplier to retry
+     * @param <T> the return type
+     * @return the return value of the given supplier once it runs successfully
+     */
+    private <T> T retryUntilSuccess(Supplier<T> supplier) {
+        return Tools.retryable(
+                supplier,
+                StorageException.ConcurrentModification.class,
+                Integer.MAX_VALUE,
+                MAX_RETRY_DELAY_MILLIS)
+                .get();
     }
 
-    private void registerMessageHandlers(ExecutorService executor) {
-
-        clusterCommunicator.addSubscriber(APPLY_BATCH_FLOWS, new OnStoreBatch(), executor);
-        clusterCommunicator.<FlowRuleBatchEvent>addSubscriber(
-                REMOTE_APPLY_COMPLETED, serializer::decode, this::notifyDelegate, executor);
-        clusterCommunicator.addSubscriber(
-                GET_FLOW_ENTRY, serializer::decode, flowTable::getFlowEntry, serializer::encode, executor);
-        clusterCommunicator.addSubscriber(
-                GET_DEVICE_FLOW_ENTRIES, serializer::decode, flowTable::getFlowEntries, serializer::encode, executor);
-        clusterCommunicator.addSubscriber(
-                REMOVE_FLOW_ENTRY, serializer::decode, this::removeFlowRuleInternal, serializer::encode, executor);
-        clusterCommunicator.addSubscriber(
-                FLOW_TABLE_BACKUP, serializer::decode, flowTable::onBackupReceipt, serializer::encode, executor);
+    /**
+     * Return method for {@link #retryUntilSuccess(Supplier)} callbacks to indicate that the callback needs to be
+     * retried after a randomized delay.
+     *
+     * @param <T> the return type
+     * @return nothing
+     * @throws StorageException.ConcurrentModification to force a retry of the callback
+     */
+    private <T> T retry() {
+        throw RETRY;
     }
 
-    private void unregisterMessageHandlers() {
-        clusterCommunicator.removeSubscriber(REMOVE_FLOW_ENTRY);
-        clusterCommunicator.removeSubscriber(GET_DEVICE_FLOW_ENTRIES);
-        clusterCommunicator.removeSubscriber(GET_FLOW_ENTRY);
-        clusterCommunicator.removeSubscriber(APPLY_BATCH_FLOWS);
-        clusterCommunicator.removeSubscriber(REMOTE_APPLY_COMPLETED);
-        clusterCommunicator.removeSubscriber(FLOW_TABLE_BACKUP);
+    /**
+     * Handles a flow rule batch event forwarded to the master node.
+     * <p>
+     * If this node is the master for the associated device, notifies event listeners to install flow rules.
+     *
+     * @param event the event to handle
+     */
+    private void applyFlows(FlowRuleBatchEvent event) {
+        if (mastershipService.isLocalMaster(event.deviceId())) {
+            notifyDelegate(event);
+        }
     }
 
-    private void logConfig(String prefix) {
-        log.info("{} with msgHandlerPoolSize = {}; backupPeriod = {}, backupCount = {}",
-                 prefix, msgHandlerPoolSize, backupPeriod, backupCount);
+    /**
+     * Handles a completed batch event received from the master node.
+     * <p>
+     * If this node is the source of the batch, notifies event listeners to complete the operations.
+     *
+     * @param event the event to handle
+     */
+    private void completeBatch(FlowRuleBatchEvent event) {
+        if (pendingBatches.remove(event.subject().batchId())) {
+            notifyDelegate(event);
+        }
     }
 
     // This is not a efficient operation on a distributed sharded
@@ -333,63 +263,60 @@
     @Override
     public int getFlowRuleCount() {
         return Streams.stream(deviceService.getDevices()).parallel()
-                        .mapToInt(device -> Iterables.size(getFlowEntries(device.id())))
-                        .sum();
+                .mapToInt(device -> Iterables.size(getFlowEntries(device.id())))
+                .sum();
+    }
+
+    /**
+     * Returns the {@link DocumentPath} for the given {@link DeviceId}.
+     *
+     * @param deviceId the device identifier for which to return a path
+     * @return the path for the given device
+     */
+    private DocumentPath getPathFor(DeviceId deviceId) {
+        return DocumentPath.from("root", deviceId.toString());
+    }
+
+    /**
+     * Returns the {@link DocumentPath} for the given {@link DeviceId} and {@link FlowId}.
+     *
+     * @param deviceId the device identifier for which to return the path
+     * @param flowId the flow identifier for which to return the path
+     * @return the path for the given device/flow
+     */
+    private DocumentPath getPathFor(DeviceId deviceId, FlowId flowId) {
+        return DocumentPath.from("root", deviceId.toString(), flowId.toString());
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public FlowEntry getFlowEntry(FlowRule rule) {
-        NodeId master = mastershipService.getMasterFor(rule.deviceId());
-
-        if (master == null) {
-            log.debug("Failed to getFlowEntry: No master for {}", rule.deviceId());
-            return null;
-        }
-
-        if (Objects.equals(local, master)) {
-            return flowTable.getFlowEntry(rule);
-        }
-
-        log.trace("Forwarding getFlowEntry to {}, which is the primary (master) for device {}",
-                  master, rule.deviceId());
-
-        return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive(rule,
-                                    FlowStoreMessageSubjects.GET_FLOW_ENTRY,
-                                    serializer::encode,
-                                    serializer::decode,
-                                    master),
-                               FLOW_RULE_STORE_TIMEOUT_MILLIS,
-                               TimeUnit.MILLISECONDS,
-                               null);
+        DocumentPath path = getPathFor(rule.deviceId(), rule.id());
+        Versioned<Map<StoredFlowEntry, StoredFlowEntry>> flowEntries = flows.get(path);
+        return flowEntries != null ? flowEntries.value().get(rule) : null;
     }
 
     @Override
     public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
-        NodeId master = mastershipService.getMasterFor(deviceId);
-
-        if (master == null) {
-            log.debug("Failed to getFlowEntries: No master for {}", deviceId);
+        DocumentPath path = getPathFor(deviceId);
+        try {
+            return getFlowEntries(path);
+        } catch (NoSuchDocumentPathException e) {
             return Collections.emptyList();
         }
+    }
 
-        if (Objects.equals(local, master)) {
-            return flowTable.getFlowEntries(deviceId);
-        }
-
-        log.trace("Forwarding getFlowEntries to {}, which is the primary (master) for device {}",
-                  master, deviceId);
-
-        return Tools.futureGetOrElse(clusterCommunicator.sendAndReceive(deviceId,
-                                    FlowStoreMessageSubjects.GET_DEVICE_FLOW_ENTRIES,
-                                    serializer::encode,
-                                    serializer::decode,
-                                    master),
-                               FLOW_RULE_STORE_TIMEOUT_MILLIS,
-                               TimeUnit.MILLISECONDS,
-                               Collections.emptyList());
+    @SuppressWarnings("unchecked")
+    private Iterable<FlowEntry> getFlowEntries(DocumentPath path) {
+        return flows.getChildren(path)
+                .values()
+                .stream()
+                .flatMap(v -> v.value().values().stream())
+                .collect(Collectors.toList());
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public void storeFlowRule(FlowRule rule) {
         storeBatch(new FlowRuleBatchOperation(
                 Collections.singletonList(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule)),
@@ -419,73 +346,39 @@
             return;
         }
 
-        if (Objects.equals(local, master)) {
-            storeBatchInternal(operation);
-            return;
-        }
+        pendingBatches.add(operation.id());
 
-        log.trace("Forwarding storeBatch to {}, which is the primary (master) for device {}",
-                  master, deviceId);
-
-        clusterCommunicator.unicast(operation,
-                                    APPLY_BATCH_FLOWS,
-                                    serializer::encode,
-                                    master)
-                           .whenComplete((result, error) -> {
-                               if (error != null) {
-                                   log.warn("Failed to storeBatch: {} to {}", operation, master, error);
-
-                                   Set<FlowRule> allFailures = operation.getOperations()
-                                           .stream()
-                                           .map(op -> op.target())
-                                           .collect(Collectors.toSet());
-
-                                   notifyDelegate(FlowRuleBatchEvent.completed(
-                                           new FlowRuleBatchRequest(operation.id(), Collections.emptySet()),
-                                           new CompletedBatchOperation(false, allFailures, deviceId)));
-                               }
-                           });
-    }
-
-    private void storeBatchInternal(FlowRuleBatchOperation operation) {
-
-        final DeviceId did = operation.deviceId();
-        //final Collection<FlowEntry> ft = flowTable.getFlowEntries(did);
         Set<FlowRuleBatchEntry> currentOps = updateStoreInternal(operation);
         if (currentOps.isEmpty()) {
             batchOperationComplete(FlowRuleBatchEvent.completed(
                     new FlowRuleBatchRequest(operation.id(), Collections.emptySet()),
-                    new CompletedBatchOperation(true, Collections.emptySet(), did)));
-            return;
+                    new CompletedBatchOperation(true, Collections.emptySet(), deviceId)));
+        } else if (Objects.equals(local, master)) {
+            notifyDelegate(FlowRuleBatchEvent.requested(
+                    new FlowRuleBatchRequest(operation.id(), currentOps),
+                    operation.deviceId()));
+        } else {
+            clusterCommunicator.unicast(FlowRuleBatchEvent.requested(
+                    new FlowRuleBatchRequest(operation.id(), currentOps),
+                    operation.deviceId()),
+                    APPLY_FLOWS,
+                    serializer::encode,
+                    master);
         }
-
-        notifyDelegate(FlowRuleBatchEvent.requested(new
-                           FlowRuleBatchRequest(operation.id(),
-                                                currentOps), operation.deviceId()));
     }
 
     private Set<FlowRuleBatchEntry> updateStoreInternal(FlowRuleBatchOperation operation) {
         return operation.getOperations().stream().map(
                 op -> {
-                    StoredFlowEntry entry;
                     switch (op.operator()) {
                         case ADD:
-                            entry = new DefaultFlowEntry(op.target());
-                            // always add requested FlowRule
-                            // Note: 2 equal FlowEntry may have different treatment
-                            flowTable.remove(entry.deviceId(), entry);
-                            flowTable.add(entry);
-
+                            addBatchEntry(op);
                             return op;
                         case REMOVE:
-                            entry = flowTable.getFlowEntry(op.target());
-                            if (entry != null) {
-                                //FIXME modification of "stored" flow entry outside of flow table
-                                entry.setState(FlowEntryState.PENDING_REMOVE);
-                                log.debug("Setting state of rule to pending remove: {}", entry);
+                            if (removeBatchEntry(op)) {
                                 return op;
                             }
-                            break;
+                            return null;
                         case MODIFY:
                             //TODO: figure this out at some point
                             break;
@@ -497,6 +390,66 @@
         ).filter(Objects::nonNull).collect(Collectors.toSet());
     }
 
+    @SuppressWarnings("unchecked")
+    private void addBatchEntry(FlowRuleBatchEntry batchEntry) {
+        StoredFlowEntry entry = new DefaultFlowEntry(batchEntry.target());
+        DocumentPath path = getPathFor(entry.deviceId(), entry.id());
+        retryUntilSuccess(() -> {
+            Versioned<Map<StoredFlowEntry, StoredFlowEntry>> value = flows.get(path);
+            if (value != null) {
+                Map<StoredFlowEntry, StoredFlowEntry> entries = Maps.newHashMap(value.value());
+                entries.put(entry, entry);
+                if (flows.replace(path, entries, value.version())) {
+                    log.trace("Stored new flow rule: {}", entry);
+                    return null;
+                } else {
+                    log.trace("Failed to store new flow rule: {}", entry);
+                    return retry();
+                }
+            } else {
+                // If there are no entries stored for the device, initialize the device's flows.
+                flows.createRecursive(path, Maps.newHashMap());
+                return retry();
+            }
+        });
+    }
+
+    @SuppressWarnings("unchecked")
+    private boolean removeBatchEntry(FlowRuleBatchEntry batchEntry) {
+        FlowRule rule = batchEntry.target();
+        DocumentPath path = getPathFor(rule.deviceId(), rule.id());
+        return retryUntilSuccess(() -> {
+            Versioned<Map<StoredFlowEntry, StoredFlowEntry>> value = flows.get(path);
+            if (value != null) {
+                Map<StoredFlowEntry, StoredFlowEntry> entries = Maps.newHashMap(value.value());
+                StoredFlowEntry entry = entries.get(rule);
+                if (entry != null) {
+                    entry.setState(FlowEntryState.PENDING_REMOVE);
+                    if (flows.replace(path, entries, value.version())) {
+                        log.trace("Updated flow rule state to PENDING_REMOVE: {}", entry);
+                        return true;
+                    } else {
+                        log.trace("Failed to update flow rule state to PENDING_REMOVE: {}", entry);
+                        return retry();
+                    }
+                } else {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+        });
+    }
+
+    @Override
+    public void batchOperationComplete(FlowRuleBatchEvent event) {
+        if (pendingBatches.remove(event.subject().batchId())) {
+            notifyDelegate(event);
+        } else {
+            clusterCommunicator.broadcast(event, COMPLETE_BATCH, serializer::encode);
+        }
+    }
+
     @Override
     public void deleteFlowRule(FlowRule rule) {
         storeBatch(
@@ -509,426 +462,142 @@
 
     @Override
     public FlowRuleEvent pendingFlowRule(FlowEntry rule) {
-        if (mastershipService.isLocalMaster(rule.deviceId())) {
-            StoredFlowEntry stored = flowTable.getFlowEntry(rule);
-            if (stored != null &&
-                    stored.state() != FlowEntryState.PENDING_ADD) {
-                stored.setState(FlowEntryState.PENDING_ADD);
-                return new FlowRuleEvent(Type.RULE_UPDATED, rule);
+        DocumentPath path = getPathFor(rule.deviceId(), rule.id());
+        return retryUntilSuccess(() -> {
+            Versioned<Map<StoredFlowEntry, StoredFlowEntry>> value = flows.get(path);
+            if (value != null) {
+                Map<StoredFlowEntry, StoredFlowEntry> entries = Maps.newHashMap(value.value());
+                StoredFlowEntry entry = entries.get(rule);
+                if (entry != null && entry.state() != FlowEntryState.PENDING_ADD) {
+                    entry.setState(FlowEntryState.PENDING_ADD);
+                    if (flows.replace(path, entries, value.version())) {
+                        log.trace("Updated flow rule state to PENDING_ADD: {}", entry);
+                        return new FlowRuleEvent(RULE_UPDATED, rule);
+                    } else {
+                        log.trace("Failed to update flow rule state to PENDING_ADD: {}", entry);
+                        return retry();
+                    }
+                } else {
+                    return null;
+                }
+            } else {
+                return null;
             }
-        }
-        return null;
+        });
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public FlowRuleEvent addOrUpdateFlowRule(FlowEntry rule) {
-        NodeId master = mastershipService.getMasterFor(rule.deviceId());
-        if (Objects.equals(local, master)) {
-            return addOrUpdateFlowRuleInternal(rule);
-        }
+        DocumentPath path = getPathFor(rule.deviceId(), rule.id());
+        return retryUntilSuccess(() -> {
+            Versioned<Map<StoredFlowEntry, StoredFlowEntry>> value = flows.get(path);
+            if (value != null) {
+                Map<StoredFlowEntry, StoredFlowEntry> entries = Maps.newHashMap(value.value());
+                StoredFlowEntry entry = entries.get(rule);
+                if (entry != null) {
+                    FlowRuleEvent event;
+                    String message;
 
-        log.warn("Tried to update FlowRule {} state,"
-                         + " while the Node was not the master.", rule);
-        return null;
-    }
+                    entry.setBytes(rule.bytes());
+                    entry.setLife(rule.life(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS);
+                    entry.setLiveType(rule.liveType());
+                    entry.setPackets(rule.packets());
+                    entry.setLastSeen();
 
-    private FlowRuleEvent addOrUpdateFlowRuleInternal(FlowEntry rule) {
-        // check if this new rule is an update to an existing entry
-        StoredFlowEntry stored = flowTable.getFlowEntry(rule);
-        if (stored != null) {
-            //FIXME modification of "stored" flow entry outside of flow table
-            stored.setBytes(rule.bytes());
-            stored.setLife(rule.life(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS);
-            stored.setLiveType(rule.liveType());
-            stored.setPackets(rule.packets());
-            stored.setLastSeen();
-            if (stored.state() == FlowEntryState.PENDING_ADD) {
-                stored.setState(FlowEntryState.ADDED);
-                return new FlowRuleEvent(Type.RULE_ADDED, rule);
+                    // If the entry state is PENDING_ADD, set it to ADDED. Otherwise, just update the rule.
+                    if (entry.state() == FlowEntryState.PENDING_ADD) {
+                        entry.setState(FlowEntryState.ADDED);
+                        event = new FlowRuleEvent(Type.RULE_ADDED, rule);
+                        message = "Updated flow rule state to ADDED: {}";
+                    } else {
+                        event = new FlowRuleEvent(Type.RULE_UPDATED, rule);
+                        message = "Updated flow rule: {}";
+                    }
+
+                    if (flows.replace(path, entries, value.version())) {
+                        log.trace(message, entry);
+                        return event;
+                    } else {
+                        log.trace("Failed to update flow rule: {}", entry);
+                        return retry();
+                    }
+                } else {
+                    // If the rule does not exist, return null. Inserting the rule risks race conditions
+                    // that can result in removed rules being retained.
+                    return null;
+                }
+            } else {
+                // If there are no entries stored for the device, initialize the device's flows.
+                flows.createRecursive(path, Maps.newHashMap());
+                return retry();
             }
-            return new FlowRuleEvent(Type.RULE_UPDATED, rule);
-        }
-
-        // TODO: Confirm if this behavior is correct. See SimpleFlowRuleStore
-        // TODO: also update backup if the behavior is correct.
-        flowTable.add(rule);
-        return null;
+        });
     }
 
     @Override
+    @SuppressWarnings("unchecked")
     public FlowRuleEvent removeFlowRule(FlowEntry rule) {
-        final DeviceId deviceId = rule.deviceId();
-        NodeId master = mastershipService.getMasterFor(deviceId);
-
-        if (Objects.equals(local, master)) {
-            // bypass and handle it locally
-            return removeFlowRuleInternal(rule);
-        }
-
-        if (master == null) {
-            log.warn("Failed to removeFlowRule: No master for {}", deviceId);
-            // TODO: revisit if this should be null (="no-op") or Exception
-            return null;
-        }
-
-        log.trace("Forwarding removeFlowRule to {}, which is the master for device {}",
-                  master, deviceId);
-
-        return Futures.getUnchecked(clusterCommunicator.sendAndReceive(
-                               rule,
-                               REMOVE_FLOW_ENTRY,
-                               serializer::encode,
-                               serializer::decode,
-                               master));
-    }
-
-    private FlowRuleEvent removeFlowRuleInternal(FlowEntry rule) {
-        final DeviceId deviceId = rule.deviceId();
-        // This is where one could mark a rule as removed and still keep it in the store.
-        final FlowEntry removed = flowTable.remove(deviceId, rule);
-        // rule may be partial rule that is missing treatment, we should use rule from store instead
-        return removed != null ? new FlowRuleEvent(RULE_REMOVED, removed) : null;
+        DocumentPath path = getPathFor(rule.deviceId(), rule.id());
+        return retryUntilSuccess(() -> {
+            Versioned<Map<StoredFlowEntry, StoredFlowEntry>> value = flows.get(path);
+            if (value != null) {
+                Map<StoredFlowEntry, StoredFlowEntry> entries = Maps.newHashMap(value.value());
+                StoredFlowEntry entry = entries.remove(rule);
+                if (entry != null) {
+                    if (flows.replace(path, entries, value.version())) {
+                        log.trace("Removed flow rule: {}", entry);
+                        return new FlowRuleEvent(RULE_REMOVED, entry);
+                    } else {
+                        log.trace("Failed to remove flow rule: {}", entry);
+                        return retry();
+                    }
+                } else {
+                    return null;
+                }
+            } else {
+                return null;
+            }
+        });
     }
 
     @Override
     public void purgeFlowRule(DeviceId deviceId) {
-        flowTable.purgeFlowRule(deviceId);
+        DocumentPath path = getPathFor(deviceId);
+        try {
+            for (String flowId : flows.getChildren(path).keySet()) {
+                flows.removeNode(DocumentPath.from("root", deviceId.toString(), flowId));
+            }
+        } catch (NoSuchDocumentPathException e) {
+            // Do nothing
+        }
+        try {
+            flows.removeNode(path);
+        } catch (NoSuchDocumentPathException e) {
+            // Do nothing
+        }
     }
 
     @Override
     public void purgeFlowRules() {
-        flowTable.purgeFlowRules();
-    }
-
-    @Override
-    public void batchOperationComplete(FlowRuleBatchEvent event) {
-        //FIXME: need a per device pending response
-        NodeId nodeId = pendingResponses.remove(event.subject().batchId());
-        if (nodeId == null) {
-            notifyDelegate(event);
-        } else {
-            // TODO check unicast return value
-            clusterCommunicator.unicast(event, REMOTE_APPLY_COMPLETED, serializer::encode, nodeId);
-            //error log: log.warn("Failed to respond to peer for batch operation result");
-        }
-    }
-
-    private final class OnStoreBatch implements ClusterMessageHandler {
-
-        @Override
-        public void handle(final ClusterMessage message) {
-            FlowRuleBatchOperation operation = serializer.decode(message.payload());
-            log.debug("received batch request {}", operation);
-
-            final DeviceId deviceId = operation.deviceId();
-            NodeId master = mastershipService.getMasterFor(deviceId);
-            if (!Objects.equals(local, master)) {
-                Set<FlowRule> failures = new HashSet<>(operation.size());
-                for (FlowRuleBatchEntry op : operation.getOperations()) {
-                    failures.add(op.target());
-                }
-                CompletedBatchOperation allFailed = new CompletedBatchOperation(false, failures, deviceId);
-                // This node is no longer the master, respond as all failed.
-                // TODO: we might want to wrap response in envelope
-                // to distinguish sw programming failure and hand over
-                // it make sense in the latter case to retry immediately.
-                message.respond(serializer.encode(allFailed));
-                return;
+        try {
+            for (String deviceId : flows.getChildren(flows.root()).keySet()) {
+                purgeFlowRule(DeviceId.deviceId(deviceId));
             }
-
-            pendingResponses.put(operation.id(), message.sender());
-            storeBatchInternal(operation);
-        }
-    }
-
-    private class BackupOperation {
-        private final NodeId nodeId;
-        private final DeviceId deviceId;
-
-        public BackupOperation(NodeId nodeId, DeviceId deviceId) {
-            this.nodeId = nodeId;
-            this.deviceId = deviceId;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(nodeId, deviceId);
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (other != null && other instanceof BackupOperation) {
-                BackupOperation that = (BackupOperation) other;
-                return this.nodeId.equals(that.nodeId) &&
-                        this.deviceId.equals(that.deviceId);
-            } else {
-                return false;
-            }
-        }
-    }
-
-    private class InternalFlowTable implements ReplicaInfoEventListener {
-
-        //TODO replace the Map<V,V> with ExtendedSet
-        private final Map<DeviceId, Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>>>
-                flowEntries = Maps.newConcurrentMap();
-
-        private final Map<BackupOperation, Long> lastBackupTimes = Maps.newConcurrentMap();
-        private final Map<DeviceId, Long> lastUpdateTimes = Maps.newConcurrentMap();
-
-        @Override
-        public void event(ReplicaInfoEvent event) {
-            eventHandler.execute(() -> handleEvent(event));
-        }
-
-        private void handleEvent(ReplicaInfoEvent event) {
-            DeviceId deviceId = event.subject();
-            if (!mastershipService.isLocalMaster(deviceId)) {
-                return;
-            }
-            if (event.type() == MASTER_CHANGED) {
-                lastUpdateTimes.put(deviceId, System.currentTimeMillis());
-            }
-            backupSenderExecutor.schedule(this::backup, 0, TimeUnit.SECONDS);
-        }
-
-        private void sendBackups(NodeId nodeId, Set<DeviceId> deviceIds) {
-            // split up the devices into smaller batches and send them separately.
-            Iterables.partition(deviceIds, FLOW_TABLE_BACKUP_BATCH_SIZE)
-                     .forEach(ids -> backupFlowEntries(nodeId, Sets.newHashSet(ids)));
-        }
-
-        private void backupFlowEntries(NodeId nodeId, Set<DeviceId> deviceIds) {
-            if (deviceIds.isEmpty()) {
-                return;
-            }
-            log.debug("Sending flowEntries for devices {} to {} for backup.", deviceIds, nodeId);
-            Map<DeviceId, Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>>>
-                    deviceFlowEntries = Maps.newConcurrentMap();
-            deviceIds.forEach(id -> deviceFlowEntries.put(id, getFlowTableCopy(id)));
-            clusterCommunicator.<Map<DeviceId,
-                                 Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>>>,
-                                 Set<DeviceId>>
-                    sendAndReceive(deviceFlowEntries,
-                                   FLOW_TABLE_BACKUP,
-                                   serializer::encode,
-                                   serializer::decode,
-                                   nodeId)
-                    .whenComplete((backedupDevices, error) -> {
-                        Set<DeviceId> devicesNotBackedup = error != null ?
-                            deviceFlowEntries.keySet() :
-                            Sets.difference(deviceFlowEntries.keySet(), backedupDevices);
-                        if (devicesNotBackedup.size() > 0) {
-                            log.warn("Failed to backup devices: {}. Reason: {}, Node: {}",
-                                     devicesNotBackedup, error != null ? error.getMessage() : "none",
-                                     nodeId);
-                        }
-                        if (backedupDevices != null) {
-                            backedupDevices.forEach(id -> {
-                                lastBackupTimes.put(new BackupOperation(nodeId, id), System.currentTimeMillis());
-                            });
-                        }
-                    });
-        }
-
-        /**
-         * Returns the flow table for specified device.
-         *
-         * @param deviceId identifier of the device
-         * @return Map representing Flow Table of given device.
-         */
-        private Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>> getFlowTable(DeviceId deviceId) {
-            if (persistenceEnabled) {
-                return flowEntries.computeIfAbsent(deviceId, id -> persistenceService
-                        .<FlowId, Map<StoredFlowEntry, StoredFlowEntry>>persistentMapBuilder()
-                        .withName("FlowTable:" + deviceId.toString())
-                        .withSerializer(new Serializer() {
-                            @Override
-                            public <T> byte[] encode(T object) {
-                                return serializer.encode(object);
-                            }
-
-                            @Override
-                            public <T> T decode(byte[] bytes) {
-                                return serializer.decode(bytes);
-                            }
-
-                            @Override
-                            public <T> T copy(T object) {
-                                return serializer.copy(object);
-                            }
-                        })
-                        .build());
-            } else {
-                return flowEntries.computeIfAbsent(deviceId, id -> Maps.newConcurrentMap());
-            }
-        }
-
-        private Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>> getFlowTableCopy(DeviceId deviceId) {
-            Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>> copy = Maps.newHashMap();
-            if (persistenceEnabled) {
-                return flowEntries.computeIfAbsent(deviceId, id -> persistenceService
-                        .<FlowId, Map<StoredFlowEntry, StoredFlowEntry>>persistentMapBuilder()
-                        .withName("FlowTable:" + deviceId.toString())
-                        .withSerializer(new Serializer() {
-                            @Override
-                            public <T> byte[] encode(T object) {
-                                return serializer.encode(object);
-                            }
-
-                            @Override
-                            public <T> T decode(byte[] bytes) {
-                                return serializer.decode(bytes);
-                            }
-
-                            @Override
-                            public <T> T copy(T object) {
-                                return serializer.copy(object);
-                            }
-                        })
-                        .build());
-            } else {
-                flowEntries.computeIfAbsent(deviceId, id -> Maps.newConcurrentMap()).forEach((k, v) -> {
-                    copy.put(k, Maps.newHashMap(v));
-                });
-                return copy;
-            }
-        }
-
-        private Map<StoredFlowEntry, StoredFlowEntry> getFlowEntriesInternal(DeviceId deviceId, FlowId flowId) {
-            return getFlowTable(deviceId).computeIfAbsent(flowId, id -> Maps.newConcurrentMap());
-        }
-
-        private StoredFlowEntry getFlowEntryInternal(FlowRule rule) {
-            return getFlowEntriesInternal(rule.deviceId(), rule.id()).get(rule);
-        }
-
-        private Set<FlowEntry> getFlowEntriesInternal(DeviceId deviceId) {
-            return getFlowTable(deviceId).values().stream()
-                        .flatMap(m -> m.values().stream())
-                        .collect(Collectors.toSet());
-        }
-
-        public StoredFlowEntry getFlowEntry(FlowRule rule) {
-            return getFlowEntryInternal(rule);
-        }
-
-        public Set<FlowEntry> getFlowEntries(DeviceId deviceId) {
-            return getFlowEntriesInternal(deviceId);
-        }
-
-        public void add(FlowEntry rule) {
-            getFlowEntriesInternal(rule.deviceId(), rule.id())
-                    .compute((StoredFlowEntry) rule, (k, stored) -> {
-                        //TODO compare stored and rule timestamps
-                        //TODO the key is not updated
-                        return (StoredFlowEntry) rule;
-                    });
-            lastUpdateTimes.put(rule.deviceId(), System.currentTimeMillis());
-        }
-
-        public FlowEntry remove(DeviceId deviceId, FlowEntry rule) {
-            final AtomicReference<FlowEntry> removedRule = new AtomicReference<>();
-            getFlowEntriesInternal(rule.deviceId(), rule.id())
-                .computeIfPresent((StoredFlowEntry) rule, (k, stored) -> {
-                    if (rule instanceof DefaultFlowEntry) {
-                        DefaultFlowEntry toRemove = (DefaultFlowEntry) rule;
-                        if (stored instanceof DefaultFlowEntry) {
-                            DefaultFlowEntry storedEntry = (DefaultFlowEntry) stored;
-                            if (toRemove.created() < storedEntry.created()) {
-                                log.debug("Trying to remove more recent flow entry {} (stored: {})",
-                                          toRemove, stored);
-                                // the key is not updated, removedRule remains null
-                                return stored;
-                            }
-                        }
-                    }
-                    removedRule.set(stored);
-                    return null;
-                });
-
-            if (removedRule.get() != null) {
-                lastUpdateTimes.put(deviceId, System.currentTimeMillis());
-                return removedRule.get();
-            } else {
-                return null;
-            }
-        }
-
-        public void purgeFlowRule(DeviceId deviceId) {
-            flowEntries.remove(deviceId);
-        }
-
-        public void purgeFlowRules() {
-            flowEntries.clear();
-        }
-
-        private List<NodeId> getBackupNodes(DeviceId deviceId) {
-            // The returned backup node list is in the order of preference i.e. next likely master first.
-            List<NodeId> allPossibleBackupNodes = replicaInfoManager.getReplicaInfoFor(deviceId).backups();
-            return ImmutableList.copyOf(allPossibleBackupNodes)
-                                .subList(0, Math.min(allPossibleBackupNodes.size(), backupCount));
-        }
-
-        private void backup() {
-            try {
-                // compute a mapping from node to the set of devices whose flow entries it should backup
-                Map<NodeId, Set<DeviceId>> devicesToBackupByNode = Maps.newHashMap();
-                flowEntries.keySet().forEach(deviceId -> {
-                    List<NodeId> backupNodes = getBackupNodes(deviceId);
-                    backupNodes.forEach(backupNode -> {
-                            if (lastBackupTimes.getOrDefault(new BackupOperation(backupNode, deviceId), 0L)
-                                    < lastUpdateTimes.getOrDefault(deviceId, 0L)) {
-                                devicesToBackupByNode.computeIfAbsent(backupNode,
-                                                                      nodeId -> Sets.newHashSet()).add(deviceId);
-                            }
-                    });
-                });
-                // send the device flow entries to their respective backup nodes
-                devicesToBackupByNode.forEach(this::sendBackups);
-            } catch (Exception e) {
-                log.error("Backup failed.", e);
-            }
-        }
-
-        private Set<DeviceId> onBackupReceipt(Map<DeviceId,
-                Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>>> flowTables) {
-            log.debug("Received flowEntries for {} to backup", flowTables.keySet());
-            Set<DeviceId> backedupDevices = Sets.newHashSet();
-            try {
-                flowTables.forEach((deviceId, deviceFlowTable) -> {
-                    // Only process those devices are that not managed by the local node.
-                    if (!Objects.equals(local, mastershipService.getMasterFor(deviceId))) {
-                        Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>> backupFlowTable =
-                                getFlowTable(deviceId);
-                        backupFlowTable.clear();
-                        backupFlowTable.putAll(deviceFlowTable);
-                        backedupDevices.add(deviceId);
-                    }
-                });
-            } catch (Exception e) {
-                log.warn("Failure processing backup request", e);
-            }
-            return backedupDevices;
+        } catch (NoSuchDocumentPathException e) {
+            // Do nothing
         }
     }
 
     @Override
     public FlowRuleEvent updateTableStatistics(DeviceId deviceId,
-                                               List<TableStatisticsEntry> tableStats) {
+            List<TableStatisticsEntry> tableStats) {
         deviceTableStats.put(deviceId, tableStats);
         return null;
     }
 
     @Override
     public Iterable<TableStatisticsEntry> getTableStatistics(DeviceId deviceId) {
-        NodeId master = mastershipService.getMasterFor(deviceId);
-
-        if (master == null) {
-            log.debug("Failed to getTableStats: No master for {}", deviceId);
-            return Collections.emptyList();
-        }
-
         List<TableStatisticsEntry> tableStats = deviceTableStats.get(deviceId);
         if (tableStats == null) {
             return Collections.emptyList();
@@ -944,11 +613,11 @@
     }
 
     private class InternalTableStatsListener
-        implements EventuallyConsistentMapListener<DeviceId, List<TableStatisticsEntry>> {
+            implements EventuallyConsistentMapListener<DeviceId, List<TableStatisticsEntry>> {
         @Override
         public void event(EventuallyConsistentMapEvent<DeviceId,
-                          List<TableStatisticsEntry>> event) {
+                List<TableStatisticsEntry>> event) {
             //TODO: Generate an event to listeners (do we need?)
         }
     }
-}
+}
\ No newline at end of file
