diff --git a/src/main/java/edu/caltech/nanodb/server/NanoDBServer.java b/src/main/java/edu/caltech/nanodb/server/NanoDBServer.java
index a9cd65576b3f315923996b1f2640862f7bb2cfd4..0034fbde2f64a778e03b754f90dc9d288fdb48fd 100644
--- a/src/main/java/edu/caltech/nanodb/server/NanoDBServer.java
+++ b/src/main/java/edu/caltech/nanodb/server/NanoDBServer.java
@@ -72,69 +72,6 @@ public class NanoDBServer implements ServerProperties {
     private ReentrantReadWriteLock schemaLock;
 
 
-    /**
-     * Initialize all of the properties that the database server knows about.
-     * Some of these properties are read-write, and others are read-only and
-     * are initialized right at database startup, before any other steps
-     * occur.
-     */
-    private void initProperties() {
-        propertyRegistry.addProperty(PROP_BASE_DIRECTORY,
-            new StringValueValidator(), DEFAULT_BASE_DIRECTORY,
-            /* readonly */ true);
-
-        propertyRegistry.addProperty(PROP_PAGECACHE_SIZE,
-            new IntegerValueValidator(MIN_PAGECACHE_SIZE, MAX_PAGECACHE_SIZE),
-            DEFAULT_PAGECACHE_SIZE);
-
-        propertyRegistry.addProperty(PROP_PAGECACHE_POLICY,
-            new StringEnumValidator(PAGECACHE_POLICY_VALUES),
-            DEFAULT_PAGECACHE_POLICY);
-
-        propertyRegistry.addProperty(PROP_PAGE_SIZE,
-            new IntegerValueValidator(DBFile::isValidPageSize,
-                "Specified page-size %d is invalid."), DEFAULT_PAGE_SIZE);
-
-        propertyRegistry.addProperty(PROP_ENABLE_TRANSACTIONS,
-            new BooleanFlagValidator(), false, /* readonly */ true);
-
-        propertyRegistry.addProperty(PROP_ENFORCE_KEY_CONSTRAINTS,
-            new BooleanFlagValidator(), true);
-
-        propertyRegistry.addProperty(PROP_ENABLE_INDEXES,
-            new BooleanFlagValidator(), false, /* reaadonly */ true);
-
-        propertyRegistry.addProperty(PROP_CREATE_INDEXES_ON_KEYS,
-            new BooleanFlagValidator(), false);
-
-        propertyRegistry.addProperty(PROP_PLANNER_CLASS,
-            new PlannerClassValidator(), DEFAULT_PLANNER_CLASS);
-
-        propertyRegistry.addProperty(PROP_FLUSH_AFTER_CMD,
-            new BooleanFlagValidator(), true);
-    }
-
-
-    /**
-     * This helper function sets the NanoDB server properties based on the
-     * contents of a Java {@code Properties} object.  This allows us to set
-     * NanoDB properties from system properties and/or other sources of
-     * properties.
-     *
-     * @param properties the properties to apply to NanoDB's configuration.
-     */
-    private void setProperties(Properties properties) {
-        if (properties == null)
-            throw new IllegalArgumentException("properties cannot be null");
-
-        for (String name : properties.stringPropertyNames()) {
-            if (propertyRegistry.hasProperty(name))
-                propertyRegistry.setPropertyValue(name,
-                    properties.getProperty(name));
-        }
-    }
-
-
     /**
      * This static method encapsulates all of the operations necessary for
      * cleanly starting the NanoDB server.  Database server properties are
@@ -166,13 +103,12 @@ public class NanoDBServer implements ServerProperties {
 
         // Everything needs configuration.
         propertyRegistry = new PropertyRegistry();
-        initProperties();
 
         // Apply system properties first (populated from e.g. command line),
         // then override with any arguments to this function.
-        setProperties(System.getProperties());
+        propertyRegistry.setProperties(System.getProperties());
         if (initialProperties != null)
-            setProperties(initialProperties);
+            propertyRegistry.setProperties(initialProperties);
 
         propertyRegistry.setupCompleted();
 
diff --git a/src/main/java/edu/caltech/nanodb/server/properties/PropertyObserver.java b/src/main/java/edu/caltech/nanodb/server/properties/PropertyObserver.java
new file mode 100644
index 0000000000000000000000000000000000000000..b783c7ef09db6c0e9771a2ec86d384cfd5791310
--- /dev/null
+++ b/src/main/java/edu/caltech/nanodb/server/properties/PropertyObserver.java
@@ -0,0 +1,18 @@
+package edu.caltech.nanodb.server.properties;
+
+
+/**
+ * An interface that components can implement to be notified of changes to
+ * property-values during system operation.
+ */
+public interface PropertyObserver {
+    /**
+     * This method is called on all property observers when a given property
+     * is changed to a new value.
+     *
+     * @param propertyName the name of the property that was changed
+     *
+     * @param newValue the new value of the property
+     */
+    void propertyChanged(String propertyName, Object newValue);
+}
diff --git a/src/main/java/edu/caltech/nanodb/server/properties/PropertyRegistry.java b/src/main/java/edu/caltech/nanodb/server/properties/PropertyRegistry.java
index 2fd22b628e3d630ed2e410d7d298f186a0c3312e..734c40e67288d1caf04fb8b3d2c927b3a90ca222 100644
--- a/src/main/java/edu/caltech/nanodb/server/properties/PropertyRegistry.java
+++ b/src/main/java/edu/caltech/nanodb/server/properties/PropertyRegistry.java
@@ -1,10 +1,14 @@
 package edu.caltech.nanodb.server.properties;
 
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import edu.caltech.nanodb.storage.DBFile;
+
 
 /**
  * This is the central location where all properties exposed by the database
@@ -12,7 +16,7 @@ import java.util.concurrent.ConcurrentHashMap;
  * configurable properties with the registry, and then they can be accessed
  * and/or set from the SQL prompt.
  */
-public class PropertyRegistry {
+public class PropertyRegistry implements ServerProperties {
 
     private class PropertyDescriptor {
         /** The name of the property. */
@@ -69,6 +73,13 @@ public class PropertyRegistry {
         new ConcurrentHashMap<>();
 
 
+    /**
+     * A collection of property observers to be informed when property values
+     * change.
+     */
+    private ArrayList<PropertyObserver> observers = new ArrayList<>();
+
+
     /**
      * This flag indicates whether the database is still in "start-up mode"
      * or not.  During start-up mode, all read-only properties may also be
@@ -77,6 +88,75 @@ public class PropertyRegistry {
     private boolean setup = true;
 
 
+    public PropertyRegistry() {
+        initProperties();
+    }
+
+
+    /**
+     * Initialize all of the properties that the database server knows about.
+     * Some of these properties are read-write, and others are read-only and
+     * are initialized right at database startup, before any other steps
+     * occur.
+     *
+     * @review (donnie) It's not great that this configuration is in here.
+     *         Someday, should probably migrate it back into
+     *         {@code NanoDBServer}.
+     */
+    private void initProperties() {
+        addProperty(PROP_BASE_DIRECTORY,
+            new StringValueValidator(), DEFAULT_BASE_DIRECTORY,
+            /* readonly */ true);
+
+        addProperty(PROP_PAGECACHE_SIZE,
+            new IntegerValueValidator(MIN_PAGECACHE_SIZE, MAX_PAGECACHE_SIZE),
+            DEFAULT_PAGECACHE_SIZE);
+
+        addProperty(PROP_PAGECACHE_POLICY,
+            new StringEnumValidator(PAGECACHE_POLICY_VALUES),
+            DEFAULT_PAGECACHE_POLICY, /* readonly */ true);
+
+        addProperty(PROP_PAGE_SIZE,
+            new IntegerValueValidator(DBFile::isValidPageSize,
+                "Specified page-size %d is invalid."), DEFAULT_PAGE_SIZE);
+
+        addProperty(PROP_ENABLE_TRANSACTIONS,
+            new BooleanFlagValidator(), false, /* readonly */ true);
+
+        addProperty(PROP_ENFORCE_KEY_CONSTRAINTS,
+            new BooleanFlagValidator(), true);
+
+        addProperty(PROP_ENABLE_INDEXES,
+            new BooleanFlagValidator(), false, /* reaadonly */ true);
+
+        addProperty(PROP_CREATE_INDEXES_ON_KEYS,
+            new BooleanFlagValidator(), false);
+
+        addProperty(PROP_PLANNER_CLASS,
+            new PlannerClassValidator(), DEFAULT_PLANNER_CLASS);
+
+        addProperty(PROP_FLUSH_AFTER_CMD, new BooleanFlagValidator(), true);
+    }
+
+
+    /**
+     * This helper function sets the server properties based on the contents
+     * of a Java {@code Properties} object.  This allows us to set NanoDB
+     * properties from system properties and/or other sources of properties.
+     *
+     * @param properties the properties to apply to NanoDB's configuration.
+     */
+    public void setProperties(Properties properties) {
+        if (properties == null)
+            throw new IllegalArgumentException("properties cannot be null");
+
+        for (String name : properties.stringPropertyNames()) {
+            if (hasProperty(name))
+                setPropertyValue(name, properties.getProperty(name));
+        }
+    }
+
+
     /**
      * Records that setup has been completed, and read-only properties
      * should no longer be allowed to change.
@@ -86,6 +166,19 @@ public class PropertyRegistry {
     }
 
 
+    /**
+     * Records a property-change observer on the property registry.
+     *
+     * @param observer the observer to receive property-change notifications
+     */
+    public void addObserver(PropertyObserver observer) {
+        if (observer == null)
+            throw new IllegalArgumentException("observer cannot be null");
+
+        observers.add(observer);
+    }
+
+
     /**
      * Add a read-only or read-write property to the registry, along with a
      * type and an initial value.
@@ -168,6 +261,9 @@ public class PropertyRegistry {
         }
 
         properties.get(name).setValue(value);
+
+        for (PropertyObserver obs : observers)
+            obs.propertyChanged(name, value);
     }
 
 
diff --git a/src/main/java/edu/caltech/nanodb/storage/BufferManager.java b/src/main/java/edu/caltech/nanodb/storage/BufferManager.java
index cb738e0d712665b1014d08b54c8e2470bcc6925a..e8b33c85a70bf094ab80baef0edecaccbfbfd466 100644
--- a/src/main/java/edu/caltech/nanodb/storage/BufferManager.java
+++ b/src/main/java/edu/caltech/nanodb/storage/BufferManager.java
@@ -14,6 +14,9 @@ import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.LogManager;
 
 import edu.caltech.nanodb.server.SessionState;
+import edu.caltech.nanodb.server.properties.PropertyObserver;
+import edu.caltech.nanodb.server.properties.PropertyRegistry;
+import edu.caltech.nanodb.server.properties.ServerProperties;
 
 
 /**
@@ -29,35 +32,15 @@ import edu.caltech.nanodb.server.SessionState;
  */
 public class BufferManager {
 
-    /** The default page-cache size is defined to be 20MiB. */
-    public static final int DEFAULT_PAGECACHE_SIZE = 20 * 1024 * 1024;
-
-    /**
-     * The minimum page-cache size is defined to be 32KiB, which is really
-     * only sufficient to run smaller queries when page-pinning is working
-     * properly.
-     */
-    public static final int MIN_PAGECACHE_SIZE = 32 * 1024;
-
-    /**
-     * The system property that can be used to specify the page replacement
-     * policy in the buffer manager.
-     */
-    public static final String PROP_PAGECACHE_POLICY = "nanodb.pagecache.policy";
-
-    /** The default page-cache policy is LRU. */
-    public static final String DEFAULT_PAGECACHE_POLICY = "lru";
-
-
     /**
      * This helper class keeps track of a data page that is currently cached.
      */
     private static class CachedPageInfo {
-        public DBFile dbFile;
+        DBFile dbFile;
 
-        public int pageNo;
+        int pageNo;
 
-        public CachedPageInfo(DBFile dbFile, int pageNo) {
+        CachedPageInfo(DBFile dbFile, int pageNo) {
             if (dbFile == null)
                 throw new IllegalArgumentException("dbFile cannot be null");
 
@@ -154,34 +137,39 @@ public class BufferManager {
 
     /**
      * A string indicating the buffer manager's page replacement policy.
-     * Currently it can be "lru" or "fifo".
+     * Currently it can be "LRU" or "FIFO".
      */
     private String replacementPolicy;
 
 
-    public BufferManager(FileManager fileManager) {
-        this.fileManager = fileManager;
+    private class BufferPropertyObserver
+        implements PropertyObserver, ServerProperties {
+        public void propertyChanged(String propertyName, Object newValue) {
+            // We only care about the pagecache-size value.
+            if (PROP_PAGECACHE_SIZE.equals(propertyName)) {
+                setMaxCacheSize((Integer) newValue);
+            }
+        }
+    }
 
-        maxCacheSize = DEFAULT_PAGECACHE_SIZE;
 
-        /* TODO:  Factor out the replacement policy implementation so that
-         *        it's easier to replace/configure in the future.
-         */
-        replacementPolicy = configureReplacementPolicy();
-        cachedPages = new LinkedHashMap<>(16, 0.75f, "lru".equals(replacementPolicy));
 
-        totalBytesCached = 0;
+    public BufferManager(FileManager fileManager,
+                         PropertyRegistry propertyRegistry) {
+        this.fileManager = fileManager;
+        propertyRegistry.addObserver(new BufferPropertyObserver());
 
-        /* TODO:  Get rid of this.  Something outside of this class should
-         *        configure it when it is initialized.
+        maxCacheSize = propertyRegistry.getIntProperty(
+            ServerProperties.PROP_PAGECACHE_SIZE);
 
-        if (server != null) {
-            // Register properties that the Buffer Manager exposes.
-            server.getPropertyRegistry().registerProperties(
-                new BufferManagerPropertyHandler(),
-                PROP_PAGECACHE_POLICY, PROP_PAGECACHE_SIZE);
-        }
-         */
+        // TODO:  Factor out the replacement policy implementation so that
+        //        it's easier to replace/configure in the future.
+        replacementPolicy = propertyRegistry.getStringProperty(
+            ServerProperties.PROP_PAGECACHE_POLICY);
+        cachedPages =
+            new LinkedHashMap<>(16, 0.75f, "LRU".equals(replacementPolicy));
+
+        totalBytesCached = 0;
     }
 
 
@@ -193,9 +181,10 @@ public class BufferManager {
      * @param maxCacheSize the maximum size for the buffer cache.
      */
     public void setMaxCacheSize(int maxCacheSize) {
-        if (maxCacheSize < MIN_PAGECACHE_SIZE) {
+        if (maxCacheSize < ServerProperties.MIN_PAGECACHE_SIZE) {
             throw new IllegalArgumentException(
-                "maxCacheSize must be at least " + MIN_PAGECACHE_SIZE);
+                "maxCacheSize must be at least " +
+                ServerProperties.MIN_PAGECACHE_SIZE);
         }
 
         synchronized (guard) {
@@ -223,21 +212,6 @@ public class BufferManager {
     }
 
 
-    private String configureReplacementPolicy() {
-        String str = DEFAULT_PAGECACHE_POLICY;
-        str = str.trim().toLowerCase();
-
-        if (!("lru".equals(str) || "fifo".equals(str))) {
-            logger.error(String.format(
-                "Unrecognized value \"%s\" for page-cache replacement " +
-                "policy; using default value of LRU.",
-                System.getProperty(PROP_PAGECACHE_POLICY)));
-        }
-
-        return str;
-    }
-
-
     /**
      * Add another observer to the buffer manager.
      *
diff --git a/src/main/java/edu/caltech/nanodb/storage/StorageManager.java b/src/main/java/edu/caltech/nanodb/storage/StorageManager.java
index e795de0a4ae57f40d3d67dad5e6e882c6d42dabe..a4f65ce659c80132137053cfedd60561c529f9e4 100755
--- a/src/main/java/edu/caltech/nanodb/storage/StorageManager.java
+++ b/src/main/java/edu/caltech/nanodb/storage/StorageManager.java
@@ -13,7 +13,6 @@ import edu.caltech.nanodb.indexes.IndexManager;
 import edu.caltech.nanodb.indexes.IndexUpdater;
 import edu.caltech.nanodb.relations.DatabaseConstraintEnforcer;
 import edu.caltech.nanodb.server.EventDispatcher;
-import edu.caltech.nanodb.server.NanoDBException;
 import edu.caltech.nanodb.server.NanoDBServer;
 import edu.caltech.nanodb.server.properties.PropertyRegistry;
 import edu.caltech.nanodb.server.properties.ServerProperties;
@@ -22,7 +21,8 @@ import edu.caltech.nanodb.transactions.TransactionManager;
 
 
 /**
- *
+ * The Storage Manager provides facilities for managing files of tuples,
+ * including in-memory buffering of data pages and support for transactions.
  *
  * @todo This class requires synchronization, once we support multiple clients.
  */
@@ -32,11 +32,6 @@ public class StorageManager {
     private static Logger logger = LogManager.getLogger(StorageManager.class);
 
 
-    /*========================================================================
-     * STATIC FIELDS AND METHODS
-     */
-
-
     /*========================================================================
      * NON-STATIC FIELDS AND METHODS
      */
@@ -139,7 +134,7 @@ public class StorageManager {
         logger.info("Using base directory " + baseDir);
 
         fileManager = new FileManagerImpl(baseDir);
-        bufferManager = new BufferManager(fileManager);
+        bufferManager = new BufferManager(fileManager, serverProps);
 
         tupleFileManagers.put(DBFileType.HEAP_TUPLE_FILE,
             new HeapTupleFileManager(this));
diff --git a/src/test/java/edu/caltech/test/nanodb/storage/TestBufferManager.java b/src/test/java/edu/caltech/test/nanodb/storage/TestBufferManager.java
index 5f8cb76f1406fad0a54cf2de6a0338b5c4c36904..88f168a421554ce10f904f817cd89221fe1b9f7f 100644
--- a/src/test/java/edu/caltech/test/nanodb/storage/TestBufferManager.java
+++ b/src/test/java/edu/caltech/test/nanodb/storage/TestBufferManager.java
@@ -9,6 +9,7 @@ import org.apache.commons.io.FileUtils;
 
 import static org.mockito.Mockito.*;
 
+import edu.caltech.nanodb.server.properties.PropertyRegistry;
 import edu.caltech.test.nanodb.framework.Concurrent;
 import org.testng.annotations.Test;
 
@@ -34,7 +35,8 @@ public class TestBufferManager extends StorageTestCase {
         FileUtils.cleanDirectory(testBaseDir);
 
         FileManager fileMgr = spy(new FileManagerImpl(testBaseDir));
-        BufferManager bufMgr = new BufferManager(fileMgr);
+        BufferManager bufMgr =
+            new BufferManager(fileMgr, new PropertyRegistry());
 
         DBFile file = fileMgr.createDBFile("TestBufferManager_testBuffering",
             DBFileType.TEST_FILE, 4096);
@@ -72,7 +74,8 @@ public class TestBufferManager extends StorageTestCase {
         FileUtils.cleanDirectory(testBaseDir);
 
         FileManager fileMgr = spy(new FileManagerImpl(testBaseDir));
-        BufferManager bufMgr = new BufferManager(fileMgr);
+        BufferManager bufMgr =
+            new BufferManager(fileMgr, new PropertyRegistry());
 
         // Set the Buffer Manager's pool size to 4MiB.  This will force a
         // significant number of pool evictions during the test.
diff --git a/src/test/java/edu/caltech/test/nanodb/storage/TestDBPage.java b/src/test/java/edu/caltech/test/nanodb/storage/TestDBPage.java
index 01b5157816c21be24ca83272280d3939301c8998..fbabf6a99e566f2703c8405bf80b3fa1aa82d6fa 100644
--- a/src/test/java/edu/caltech/test/nanodb/storage/TestDBPage.java
+++ b/src/test/java/edu/caltech/test/nanodb/storage/TestDBPage.java
@@ -1,6 +1,7 @@
 package edu.caltech.test.nanodb.storage;
 
 
+import edu.caltech.nanodb.server.properties.PropertyRegistry;
 import org.testng.annotations.Test;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.AfterClass;
@@ -48,7 +49,8 @@ public class TestDBPage extends StorageTestCase {
     public void beforeClass() {
 
         fileMgr = new FileManagerImpl(testBaseDir);
-        BufferManager bufMgr = new BufferManager(fileMgr);
+        BufferManager bufMgr =
+            new BufferManager(fileMgr, new PropertyRegistry());
 
         // Get DBFile
         DBFileType type = DBFileType.HEAP_TUPLE_FILE;
diff --git a/src/test/java/edu/caltech/test/nanodb/storage/TestFileManager.java b/src/test/java/edu/caltech/test/nanodb/storage/TestFileManager.java
index f9365a867ca87efb47e1dd4ff496f3dcd648cc63..8fd10d045c87ad0597bfd64b986fbc97b531032d 100644
--- a/src/test/java/edu/caltech/test/nanodb/storage/TestFileManager.java
+++ b/src/test/java/edu/caltech/test/nanodb/storage/TestFileManager.java
@@ -4,6 +4,7 @@ package edu.caltech.test.nanodb.storage;
 import java.io.File;
 import java.io.IOException;
 
+import edu.caltech.nanodb.server.properties.PropertyRegistry;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -29,7 +30,7 @@ public class TestFileManager extends StorageTestCase {
     @BeforeClass
     public void beforeClass() {
         fileMgr = new FileManagerImpl(testBaseDir);
-        bufMgr = new BufferManager(fileMgr);
+        bufMgr = new BufferManager(fileMgr, new PropertyRegistry());
     }