diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 47ffc2e3133449396ed2e8a1d90e697418f51452..ab5e17357b46143982e50fba49a7712d218c9da1 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -11,6 +11,9 @@ It is hidden behind a false defaulted course level flag.
 Studio: Allow course authors to set their course image on the schedule
 and details page, with support for JPEG and PNG images.
 
+LMS, Studio: Centralized startup code to manage.py and wsgi.py files.
+Made studio runnable using wsgi.
+
 Blades: Took videoalpha out of alpha, replacing the old video player
 
 Common: Allow instructors to input complicated expressions as answers to
diff --git a/cms/djangoapps/contentstore/management/commands/check_course.py b/cms/djangoapps/contentstore/management/commands/check_course.py
index 2f0b0b2a2c72825239e050c2690a12bb39b0688c..13ac6af50c210516013e56a4589c2942a967a5e7 100644
--- a/cms/djangoapps/contentstore/management/commands/check_course.py
+++ b/cms/djangoapps/contentstore/management/commands/check_course.py
@@ -3,11 +3,6 @@ from xmodule.modulestore.django import modulestore
 from xmodule.modulestore.xml_importer import check_module_metadata_editability
 from xmodule.course_module import CourseDescriptor
 
-from request_cache.middleware import RequestCache
-
-from django.core.cache import get_cache
-
-CACHE = get_cache('mongo_metadata_inheritance')
 
 class Command(BaseCommand):
     help = '''Enumerates through the course and find common errors'''
@@ -21,12 +16,6 @@ class Command(BaseCommand):
         loc = CourseDescriptor.id_to_location(loc_str)
         store = modulestore()
 
-        # setup a request cache so we don't throttle the DB with all the metadata inheritance requests
-        store.set_modulestore_configuration({
-            'metadata_inheritance_cache_subsystem': CACHE,
-            'request_cache': RequestCache.get_request_cache()
-        })
-
         course = store.get_item(loc, depth=3)
 
         err_cnt = 0
diff --git a/cms/djangoapps/contentstore/management/commands/clone_course.py b/cms/djangoapps/contentstore/management/commands/clone_course.py
index aa0e076f08050e038a7ecf17d82ed6d0832e036d..5ad0da09d8f4e585bf5cb9b7e969283988fbc857 100644
--- a/cms/djangoapps/contentstore/management/commands/clone_course.py
+++ b/cms/djangoapps/contentstore/management/commands/clone_course.py
@@ -9,14 +9,10 @@ from xmodule.course_module import CourseDescriptor
 
 from auth.authz import _copy_course_group
 
+
 #
 # To run from command line: rake cms:clone SOURCE_LOC=MITx/111/Foo1 DEST_LOC=MITx/135/Foo3
 #
-from request_cache.middleware import RequestCache
-from django.core.cache import get_cache
-
-CACHE = get_cache('mongo_metadata_inheritance')
-
 class Command(BaseCommand):
     """Clone a MongoDB-backed course to another location"""
     help = 'Clone a MongoDB backed course to another location'
@@ -32,11 +28,6 @@ class Command(BaseCommand):
         mstore = modulestore('direct')
         cstore = contentstore()
 
-        mstore.set_modulestore_configuration({
-            'metadata_inheritance_cache_subsystem': CACHE,
-            'request_cache': RequestCache.get_request_cache()
-        })
-
         org, course_num, run = dest_course_id.split("/")
         mstore.ignore_write_events_on_courses.append('{0}/{1}'.format(org, course_num))
 
diff --git a/cms/djangoapps/contentstore/management/commands/delete_course.py b/cms/djangoapps/contentstore/management/commands/delete_course.py
index b0901ccfc9370c41b0910439581d6fa5b0efb3be..50f9b82e807954fc19b58194681066f5452d1d8d 100644
--- a/cms/djangoapps/contentstore/management/commands/delete_course.py
+++ b/cms/djangoapps/contentstore/management/commands/delete_course.py
@@ -9,14 +9,11 @@ from xmodule.course_module import CourseDescriptor
 from .prompt import query_yes_no
 
 from auth.authz import _delete_course_group
-from request_cache.middleware import RequestCache
-from django.core.cache import get_cache
+
 
 #
 # To run from command line: rake cms:delete_course LOC=MITx/111/Foo1
 #
-
-CACHE = get_cache('mongo_metadata_inheritance')
 class Command(BaseCommand):
     help = '''Delete a MongoDB backed course'''
 
@@ -36,11 +33,6 @@ class Command(BaseCommand):
         ms = modulestore('direct')
         cs = contentstore()
 
-        ms.set_modulestore_configuration({
-            'metadata_inheritance_cache_subsystem': CACHE,
-            'request_cache': RequestCache.get_request_cache()
-        })
-
         org, course_num, run = course_id.split("/")
         ms.ignore_write_events_on_courses.append('{0}/{1}'.format(org, course_num))
 
diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py
index 7d5cd3cbcbf49123ce286451d9532fd214b218d7..da80b25fa4a62e49174df02312dc37a684a56625 100644
--- a/cms/djangoapps/contentstore/tests/test_contentstore.py
+++ b/cms/djangoapps/contentstore/tests/test_contentstore.py
@@ -1139,12 +1139,15 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase):
 
         wrapper = MongoCollectionFindWrapper(module_store.collection.find)
         module_store.collection.find = wrapper.find
+        print module_store.metadata_inheritance_cache_subsystem
+        print module_store.request_cache
         course = module_store.get_item(location, depth=2)
 
         # make sure we haven't done too many round trips to DB
-        # note we say 4 round trips here for 1) the course, 2 & 3) for the chapters and sequentials, and
-        # 4) because of the RT due to calculating the inherited metadata
-        self.assertEqual(wrapper.counter, 4)
+        # note we say 3 round trips here for 1) the course, and 2 & 3) for the chapters and sequentials
+        # Because we're querying from the top of the tree, we cache information needed for inheritance,
+        # so we don't need to make an extra query to compute it.
+        self.assertEqual(wrapper.counter, 3)
 
         # make sure we pre-fetched a known sequential which should be at depth=2
         self.assertTrue(Location(['i4x', 'edX', 'toy', 'sequential',
diff --git a/cms/one_time_startup.py b/cms/one_time_startup.py
deleted file mode 100644
index 4198cf26379e886b44a7361ec2efa039fc5d8567..0000000000000000000000000000000000000000
--- a/cms/one_time_startup.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from dogapi import dog_http_api, dog_stats_api
-from django.conf import settings
-from xmodule.modulestore.django import modulestore
-from django.dispatch import Signal
-from request_cache.middleware import RequestCache
-
-from django.core.cache import get_cache
-
-CACHE = get_cache('mongo_metadata_inheritance')
-for store_name in settings.MODULESTORE:
-    store = modulestore(store_name)
-
-    store.set_modulestore_configuration({
-        'metadata_inheritance_cache_subsystem': CACHE,
-        'request_cache': RequestCache.get_request_cache()
-    })
-
-    modulestore_update_signal = Signal(providing_args=['modulestore', 'course_id', 'location'])
-    store.modulestore_update_signal = modulestore_update_signal
-if hasattr(settings, 'DATADOG_API'):
-    dog_http_api.api_key = settings.DATADOG_API
-    dog_stats_api.start(api_key=settings.DATADOG_API, statsd=True)
diff --git a/cms/startup.py b/cms/startup.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb1098a7074c94c3afb2e3b9ee62877146b657b7
--- /dev/null
+++ b/cms/startup.py
@@ -0,0 +1,25 @@
+"""
+Module with code executed during Studio startup
+"""
+from django.conf import settings
+
+# Force settings to run so that the python path is modified
+settings.INSTALLED_APPS  # pylint: disable=W0104
+
+from django_startup import autostartup
+
+# TODO: Remove this code once Studio/CMS runs via wsgi in all environments
+INITIALIZED = False
+
+
+def run():
+    """
+    Executed during django startup
+    """
+    global INITIALIZED
+    if INITIALIZED:
+        return
+
+    INITIALIZED = True
+    autostartup()
+
diff --git a/cms/urls.py b/cms/urls.py
index 8f396d374287ae49376756e4b526ba3cef1eaf37..1467c99b1c475d3fc868154b697e1da6a312971a 100644
--- a/cms/urls.py
+++ b/cms/urls.py
@@ -1,9 +1,9 @@
 from django.conf import settings
 from django.conf.urls import patterns, include, url
 
-# Import this file so it can do its work, even though we don't use the name.
-# pylint: disable=W0611
-from . import one_time_startup
+# TODO: This should be removed once the CMS is running via wsgi on all production servers
+import cms.startup as startup
+startup.run()
 
 # There is a course creators admin table.
 from ratelimitbackend import admin
diff --git a/cms/wsgi.py b/cms/wsgi.py
new file mode 100644
index 0000000000000000000000000000000000000000..607d7ee709fa2ad8535ec03f36c05be10d8308c4
--- /dev/null
+++ b/cms/wsgi.py
@@ -0,0 +1,12 @@
+import os
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "cms.envs.aws")
+
+import cms.startup as startup
+startup.run()
+
+# This application object is used by the development server
+# as well as any WSGI server configured to use this file.
+from django.core.wsgi import get_wsgi_application
+application = get_wsgi_application()
+
diff --git a/common/djangoapps/datadog/startup.py b/common/djangoapps/datadog/startup.py
new file mode 100644
index 0000000000000000000000000000000000000000..41949c3a94ee5c21359ea546bccb6de32520b267
--- /dev/null
+++ b/common/djangoapps/datadog/startup.py
@@ -0,0 +1,12 @@
+from django.conf import settings
+from dogapi import dog_http_api, dog_stats_api
+
+def run():
+    """
+    Initialize connection to datadog during django startup.
+
+    Expects the datadog api key in the DATADOG_API settings key
+    """
+    if hasattr(settings, 'DATADOG_API'):
+        dog_http_api.api_key = settings.DATADOG_API
+        dog_stats_api.start(api_key=settings.DATADOG_API, statsd=True)
diff --git a/common/djangoapps/terrain/browser.py b/common/djangoapps/terrain/browser.py
index 4bf1aea40c05fc4b85f2e69179f22336f547ff9f..75c0764b1bb43d42f83683ce7825060b913c846b 100644
--- a/common/djangoapps/terrain/browser.py
+++ b/common/djangoapps/terrain/browser.py
@@ -16,11 +16,6 @@ from requests import put
 from base64 import encodestring
 from json import dumps
 
-# Let the LMS and CMS do their one-time setup
-# For example, setting up mongo caches
-# These names aren't used, but do important work on import.
-from lms import one_time_startup        # pylint: disable=W0611
-from cms import one_time_startup        # pylint: disable=W0611
 from pymongo import MongoClient
 import xmodule.modulestore.django
 from xmodule.contentstore.django import _CONTENTSTORE
diff --git a/common/lib/django_startup.py b/common/lib/django_startup.py
new file mode 100644
index 0000000000000000000000000000000000000000..1987d02dd232baca56c0f433586b7c56ffe5ec1b
--- /dev/null
+++ b/common/lib/django_startup.py
@@ -0,0 +1,14 @@
+from importlib import import_module
+from django.conf import settings
+
+def autostartup():
+    """
+    Execute app.startup:run() for all installed django apps
+    """
+    for app in settings.INSTALLED_APPS:
+        try:
+            mod = import_module('{}.startup')
+            if hasattr(mod, 'run'):
+                mod.run()
+        except ImportError:
+            continue
diff --git a/common/lib/xmodule/xmodule/modulestore/__init__.py b/common/lib/xmodule/xmodule/modulestore/__init__.py
index 707390d759513207cb7be7a9cb6885fbf5358782..f2b70ad3659b6d95d290b8f2cf73821e0168b4e5 100644
--- a/common/lib/xmodule/xmodule/modulestore/__init__.py
+++ b/common/lib/xmodule/xmodule/modulestore/__init__.py
@@ -386,13 +386,6 @@ class ModuleStore(object):
         """
         raise NotImplementedError
 
-    def set_modulestore_configuration(self, config_dict):
-        '''
-        Allows for runtime configuration of the modulestore. In particular this is how the
-        application (LMS/CMS) can pass down Django related configuration information, e.g. caches, etc.
-        '''
-        raise NotImplementedError
-
     def get_modulestore_type(self, course_id):
         """
         Returns a type which identifies which modulestore is servicing the given
@@ -405,13 +398,14 @@ class ModuleStoreBase(ModuleStore):
     '''
     Implement interface functionality that can be shared.
     '''
-    def __init__(self):
+    def __init__(self, metadata_inheritance_cache_subsystem=None, request_cache=None, modulestore_update_signal=None):
         '''
         Set up the error-tracking logic.
         '''
         self._location_errors = {}  # location -> ErrorLog
-        self.modulestore_configuration = {}
-        self.modulestore_update_signal = None  # can be set by runtime to route notifications of datastore changes
+        self.metadata_inheritance_cache_subsystem = metadata_inheritance_cache_subsystem
+        self.modulestore_update_signal = modulestore_update_signal
+        self.request_cache = request_cache
 
     def _get_errorlog(self, location):
         """
@@ -455,27 +449,6 @@ class ModuleStoreBase(ModuleStore):
                 return c
         return None
 
-    @property
-    def metadata_inheritance_cache_subsystem(self):
-        """
-        Exposes an accessor to the runtime configuration for the metadata inheritance cache
-        """
-        return self.modulestore_configuration.get('metadata_inheritance_cache_subsystem', None)
-
-    @property
-    def request_cache(self):
-        """
-        Exposes an accessor to the runtime configuration for the request cache
-        """
-        return self.modulestore_configuration.get('request_cache', None)
-
-    def set_modulestore_configuration(self, config_dict):
-        """
-        This is the base implementation of the interface, all we need to do is store
-        two possible configurations as attributes on the class
-        """
-        self.modulestore_configuration = config_dict
-
 
 def namedtuple_to_son(namedtuple, prefix=''):
     """
diff --git a/common/lib/xmodule/xmodule/modulestore/django.py b/common/lib/xmodule/xmodule/modulestore/django.py
index b239e5f1d4d959d93db7f09b8e3239aefd6f4a94..9ff82e113746e6f20766c995b31eabd2e119af10 100644
--- a/common/lib/xmodule/xmodule/modulestore/django.py
+++ b/common/lib/xmodule/xmodule/modulestore/django.py
@@ -8,8 +8,17 @@ from __future__ import absolute_import
 from importlib import import_module
 
 from django.conf import settings
+from django.core.cache import get_cache, InvalidCacheBackendError
+from django.dispatch import Signal
 from xmodule.modulestore.loc_mapper_store import LocMapperStore
 
+# We may not always have the request_cache module available
+try:
+    from request_cache.middleware import RequestCache
+    HAS_REQUEST_CACHE = True
+except ImportError:
+    HAS_REQUEST_CACHE = False
+
 _MODULESTORES = {}
 
 FUNCTION_KEYS = ['render_template']
@@ -39,7 +48,20 @@ def create_modulestore_instance(engine, options):
         if key in _options and isinstance(_options[key], basestring):
             _options[key] = load_function(_options[key])
 
+    if HAS_REQUEST_CACHE:
+        request_cache = RequestCache.get_request_cache()
+    else:
+        request_cache = None
+
+    try:
+        metadata_inheritance_cache = get_cache('mongo_metadata_inheritance')
+    except InvalidCacheBackendError:
+        metadata_inheritance_cache = get_cache('default')
+
     return class_(
+        metadata_inheritance_cache_subsystem=metadata_inheritance_cache,
+        request_cache=request_cache,
+        modulestore_update_signal=Signal(providing_args=['modulestore', 'course_id', 'location']),
         **_options
     )
 
diff --git a/common/lib/xmodule/xmodule/modulestore/mixed.py b/common/lib/xmodule/xmodule/modulestore/mixed.py
index cc4ba7a6997417c4bb5fdde9339687e15996de56..8827f33360476cfc1ef22e78adbdc6abd2d5e1aa 100644
--- a/common/lib/xmodule/xmodule/modulestore/mixed.py
+++ b/common/lib/xmodule/xmodule/modulestore/mixed.py
@@ -17,12 +17,12 @@ class MixedModuleStore(ModuleStoreBase):
     """
     ModuleStore that can be backed by either XML or Mongo
     """
-    def __init__(self, mappings, stores):
+    def __init__(self, mappings, stores, **kwargs):
         """
         Initialize a MixedModuleStore. Here we look into our passed in kwargs which should be a
         collection of other modulestore configuration informations
         """
-        super(MixedModuleStore, self).__init__()
+        super(MixedModuleStore, self).__init__(**kwargs)
 
         self.modulestores = {}
         self.mappings = mappings
@@ -132,14 +132,6 @@ class MixedModuleStore(ModuleStoreBase):
         """
         return self._get_modulestore_for_courseid(course_id).get_parent_locations(location, course_id)
 
-    def set_modulestore_configuration(self, config_dict):
-        """
-        This implementation of the interface method will pass along the configuration to all ModuleStore
-        instances
-        """
-        for store in self.modulestores.values():
-            store.set_modulestore_configuration(config_dict)
-
     def get_modulestore_type(self, course_id):
         """
         Returns a type which identifies which modulestore is servicing the given
diff --git a/common/lib/xmodule/xmodule/modulestore/mongo/base.py b/common/lib/xmodule/xmodule/modulestore/mongo/base.py
index ad2732409d9398097435da60aab4642d6b2a1f62..3d10b7ab6c8efb769b804f3a85124a1fa0c4a947 100644
--- a/common/lib/xmodule/xmodule/modulestore/mongo/base.py
+++ b/common/lib/xmodule/xmodule/modulestore/mongo/base.py
@@ -270,15 +270,18 @@ class MongoModuleStore(ModuleStoreBase):
     def __init__(self, host, db, collection, fs_root, render_template,
                  port=27017, default_class=None,
                  error_tracker=null_error_tracker,
-                 user=None, password=None, **kwargs):
+                 user=None, password=None, mongo_options=None, **kwargs):
 
-        super(MongoModuleStore, self).__init__()
+        super(MongoModuleStore, self).__init__(**kwargs)
+
+        if mongo_options is None:
+            mongo_options = {}
 
         self.collection = pymongo.connection.Connection(
             host=host,
             port=port,
             tz_aware=True,
-            **kwargs
+            **mongo_options
         )[db][collection]
 
         if user is not None and password is not None:
diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
index 7e151a6649380c92e079f80d239d5e58150800b3..c5f4c2404c1214bf0e6f7ba5086be598f15c1f0a 100644
--- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
+++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py
@@ -50,15 +50,18 @@ class SplitMongoModuleStore(ModuleStoreBase):
                  port=27017, default_class=None,
                  error_tracker=null_error_tracker,
                  user=None, password=None,
+                 mongo_options=None,
                  **kwargs):
 
         ModuleStoreBase.__init__(self)
+        if mongo_options is None:
+            mongo_options = {}
 
         self.db = pymongo.database.Database(pymongo.MongoClient(
             host=host,
             port=port,
             tz_aware=True,
-            **kwargs
+            **mongo_options
         ), db)
 
         self.course_index = self.db[collection + '.active_versions']
diff --git a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
index da400e9f0aa9779f7c582746e1024400af7bd180..22d1e40c3f059a43df30e89ab0ef87bc2333a8b7 100644
--- a/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
+++ b/common/lib/xmodule/xmodule/modulestore/tests/test_mixed_modulestore.py
@@ -5,9 +5,16 @@ from uuid import uuid4
 from xmodule.tests import DATA_DIR
 from xmodule.modulestore import Location, MONGO_MODULESTORE_TYPE, XML_MODULESTORE_TYPE
 from xmodule.modulestore.exceptions import ItemNotFoundError
-from xmodule.modulestore.mixed import MixedModuleStore
 from xmodule.modulestore.xml_importer import import_from_xml
 
+# Mixed modulestore depends on django, so we'll manually configure some django settings
+# before importing the module
+from django.conf import settings
+if not settings.configured:
+    settings.configure()
+
+from xmodule.modulestore.mixed import MixedModuleStore
+
 
 HOST = 'localhost'
 PORT = 27017
@@ -234,22 +241,3 @@ class TestMixedModuleStore(object):
         assert_equals(Location(parents[0]).org, 'edX')
         assert_equals(Location(parents[0]).course, 'toy')
         assert_equals(Location(parents[0]).name, '2012_Fall')
-
-    # pylint: disable=W0212
-    def test_set_modulestore_configuration(self):
-        config = {'foo': 'bar'}
-        self.store.set_modulestore_configuration(config)
-        assert_equals(
-            config,
-            self.store._get_modulestore_for_courseid(IMPORT_COURSEID).modulestore_configuration
-        )
-
-        assert_equals(
-            config,
-            self.store._get_modulestore_for_courseid(XML_COURSEID1).modulestore_configuration
-        )
-
-        assert_equals(
-            config,
-            self.store._get_modulestore_for_courseid(XML_COURSEID2).modulestore_configuration
-        )
diff --git a/common/lib/xmodule/xmodule/modulestore/xml.py b/common/lib/xmodule/xmodule/modulestore/xml.py
index 4c2011a3e52a650c73b5cf7a7e9de95848052ee3..6527a5e34abc32b6bba4cfddafe0e09cca427542 100644
--- a/common/lib/xmodule/xmodule/modulestore/xml.py
+++ b/common/lib/xmodule/xmodule/modulestore/xml.py
@@ -257,7 +257,7 @@ class XMLModuleStore(ModuleStoreBase):
     """
     An XML backed ModuleStore
     """
-    def __init__(self, data_dir, default_class=None, course_dirs=None, load_error_modules=True):
+    def __init__(self, data_dir, default_class=None, course_dirs=None, load_error_modules=True, **kwargs):
         """
         Initialize an XMLModuleStore from data_dir
 
@@ -269,7 +269,7 @@ class XMLModuleStore(ModuleStoreBase):
         course_dirs: If specified, the list of course_dirs to load. Otherwise,
             load all course dirs
         """
-        super(XMLModuleStore, self).__init__()
+        super(XMLModuleStore, self).__init__(**kwargs)
 
         self.data_dir = path(data_dir)
         self.modules = defaultdict(dict)  # course_id -> dict(location -> XModuleDescriptor)
diff --git a/common/lib/xmodule/xmodule/peer_grading_module.py b/common/lib/xmodule/xmodule/peer_grading_module.py
index bbfc444cdc9ae15b2af64e986b7779b3761d4f3b..ae4a8b87de43927682570ed57ad721cf6181b0b2 100644
--- a/common/lib/xmodule/xmodule/peer_grading_module.py
+++ b/common/lib/xmodule/xmodule/peer_grading_module.py
@@ -8,10 +8,9 @@ from pkg_resources import resource_string
 from .capa_module import ComplexEncoder
 from .x_module import XModule
 from xmodule.raw_module import RawDescriptor
-from xmodule.modulestore.django import modulestore
 from xmodule.modulestore.exceptions import ItemNotFoundError
 from .timeinfo import TimeInfo
-from xblock.core import Dict, String, Scope, Boolean, Integer, Float
+from xblock.core import Dict, String, Scope, Boolean, Float
 from xmodule.fields import Date, Timedelta
 
 from xmodule.open_ended_grading_classes.peer_grading_service import PeerGradingService, GradingServiceError, MockPeerGradingService
@@ -104,7 +103,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
 
         if self.use_for_single_location:
             try:
-                self.linked_problem = modulestore().get_instance(self.system.course_id, self.link_to_location)
+                self.linked_problem = self.system.get_module(self.link_to_location)
             except ItemNotFoundError:
                 log.error("Linked location {0} for peer grading module {1} does not exist".format(
                     self.link_to_location, self.location))
@@ -632,3 +631,11 @@ class PeerGradingDescriptor(PeerGradingFields, RawDescriptor):
         non_editable_fields = super(PeerGradingDescriptor, self).non_editable_metadata_fields
         non_editable_fields.extend([PeerGradingFields.due, PeerGradingFields.graceperiod])
         return non_editable_fields
+
+    def get_required_module_descriptors(self):
+        """Returns a list of XModuleDescritpor instances upon which this module depends, but are
+        not children of this module"""
+        if self.use_for_single_location:
+            return [self.system.load_item(self.link_to_location)]
+        else:
+            return []
diff --git a/common/lib/xmodule/xmodule/template_module.py b/common/lib/xmodule/xmodule/template_module.py
index c28378210b5d5426fcf672397b9f321455fff566..34ba8f6c69f99e1db9812a957199e09802ec9d12 100644
--- a/common/lib/xmodule/xmodule/template_module.py
+++ b/common/lib/xmodule/xmodule/template_module.py
@@ -2,7 +2,6 @@ from xmodule.x_module import XModule
 from xmodule.raw_module import RawDescriptor
 from lxml import etree
 from mako.template import Template
-from xmodule.modulestore.django import modulestore
 
 
 class CustomTagModule(XModule):
@@ -56,7 +55,7 @@ class CustomTagDescriptor(RawDescriptor):
         # cdodge: look up the template as a module
         template_loc = self.location.replace(category='custom_tag_template', name=template_name)
 
-        template_module = modulestore().get_instance(system.course_id, template_loc)
+        template_module = system.load_item(template_loc)
         template_module_data = template_module.data
         template = Template(template_module_data)
         return template.render(**params)
diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py
index 80c4e41e8f1a58d3e3dc28ae3c09e1acc1b3ccf3..92d30fac8ca751cc60c504e14a2f7754382e4b88 100644
--- a/common/lib/xmodule/xmodule/tests/test_capa_module.py
+++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py
@@ -322,7 +322,8 @@ class CapaModuleTest(unittest.TestCase):
 
         # We have to set up Django settings in order to use QueryDict
         from django.conf import settings
-        settings.configure()
+        if not settings.configured:
+            settings.configure()
 
         # Valid GET param dict
         valid_get_dict = self._querydict_from_dict({'input_1': 'test',
diff --git a/common/lib/xmodule/xmodule/video_module.py b/common/lib/xmodule/xmodule/video_module.py
index be77cd2684266b790f833797e075888d5a7b0ea7..d846777360ea48eb622b95d457811b49e4920ade 100644
--- a/common/lib/xmodule/xmodule/video_module.py
+++ b/common/lib/xmodule/xmodule/video_module.py
@@ -24,9 +24,6 @@ from xmodule.editing_module import TabsEditingDescriptor
 from xmodule.raw_module import EmptyDataRawDescriptor
 from xmodule.xml_module import is_pointer_tag, name_to_pathname
 from xmodule.modulestore import Location
-from xmodule.modulestore.mongo import MongoModuleStore
-from xmodule.modulestore.django import modulestore
-from xmodule.contentstore.content import StaticContent
 from xblock.core import Scope, String, Boolean, Float, List, Integer
 
 import datetime
diff --git a/common/test/data/uploads/test b/common/test/data/uploads/test
index 0424951e344cc172b0784652c2b93668685f09f1..588e9fb1254e0b0e613c3420427c2af23f558d5e 100644
--- a/common/test/data/uploads/test
+++ b/common/test/data/uploads/test
@@ -1 +1 @@
-This is an arbitrary file for testing uploads
+This is an arbitrary file for testing uploads
\ No newline at end of file
diff --git a/lms/djangoapps/courseware/tests/__init__.py b/lms/djangoapps/courseware/tests/__init__.py
index 4b93e804bfc29239db4bf441dd31543028809259..64845688fb92a6d578ec126b0267edcbe4944af2 100644
--- a/lms/djangoapps/courseware/tests/__init__.py
+++ b/lms/djangoapps/courseware/tests/__init__.py
@@ -50,7 +50,8 @@ class BaseTestXmodule(ModuleStoreTestCase):
         self.course = CourseFactory.create(data=self.COURSE_DATA)
 
         # Turn off cache.
-        modulestore().set_modulestore_configuration({})
+        modulestore().request_cache = None
+        modulestore().metadata_inheritance_cache_subsystem = None
 
         chapter = ItemFactory.create(
             parent_location=self.course.location,
diff --git a/lms/djangoapps/courseware/tests/test_model_data.py b/lms/djangoapps/courseware/tests/test_model_data.py
index 0368bb040bee4d359f847d94e31712b568671225..d8682d3d5cb7a5e4248669627268c68344d7c2d2 100644
--- a/lms/djangoapps/courseware/tests/test_model_data.py
+++ b/lms/djangoapps/courseware/tests/test_model_data.py
@@ -318,8 +318,6 @@ class StorageTestBase(object):
         self.assertEquals(exception.saved_field_names[0], 'existing_field')
 
 
-
-
 class TestSettingsStorage(StorageTestBase, TestCase):
     factory = SettingsFactory
     scope = Scope.settings
diff --git a/lms/djangoapps/instructor/tests/test_legacy_gradebook.py b/lms/djangoapps/instructor/tests/test_legacy_gradebook.py
index fd285d2e3f5ee113e95353ee644ea1be24e51c8b..bca7528a96e9fbde0f0f72a2f5ab9746c6486976 100644
--- a/lms/djangoapps/instructor/tests/test_legacy_gradebook.py
+++ b/lms/djangoapps/instructor/tests/test_legacy_gradebook.py
@@ -26,7 +26,8 @@ class TestGradebook(ModuleStoreTestCase):
         self.client.login(username=instructor.username, password='test')
 
         # remove the caches
-        modulestore().set_modulestore_configuration({})
+        modulestore().request_cache = None
+        modulestore().metadata_inheritance_cache_subsystem = None
 
         kwargs = {}
         if self.grading_policy is not None:
diff --git a/lms/one_time_startup.py b/lms/one_time_startup.py
deleted file mode 100644
index 2cd2077c4e6349ea9b153d7e35d6d0375b3f204b..0000000000000000000000000000000000000000
--- a/lms/one_time_startup.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from dogapi import dog_http_api, dog_stats_api
-from django.conf import settings
-from xmodule.modulestore.django import modulestore
-from request_cache.middleware import RequestCache
-
-from django.core.cache import get_cache
-
-cache = get_cache('mongo_metadata_inheritance')
-for store_name in settings.MODULESTORE:
-    store = modulestore(store_name)
-    store.set_modulestore_configuration({
-        'metadata_inheritance_cache_subsystem': cache,
-        'request_cache': RequestCache.get_request_cache()
-    })
-
-if hasattr(settings, 'DATADOG_API'):
-    dog_http_api.api_key = settings.DATADOG_API
-    dog_stats_api.start(api_key=settings.DATADOG_API, statsd=True)
diff --git a/lms/startup.py b/lms/startup.py
new file mode 100644
index 0000000000000000000000000000000000000000..901a559edbe8c6c05b584449030b39ba3c51b793
--- /dev/null
+++ b/lms/startup.py
@@ -0,0 +1,16 @@
+"""
+Module for code that should run during LMS startup
+"""
+from django.conf import settings
+
+# Force settings to run so that the python path is modified
+settings.INSTALLED_APPS  # pylint: disable=W0104
+
+from django_startup import autostartup
+
+
+def run():
+    """
+    Executed during django startup
+    """
+    autostartup()
diff --git a/lms/urls.py b/lms/urls.py
index 53665f9ef656cce3eeae4ce4afdce6745ab54bf0..ac3dfb2a9e3a39a5140990a1779bdfea75cdea55 100644
--- a/lms/urls.py
+++ b/lms/urls.py
@@ -3,9 +3,6 @@ from django.conf.urls import patterns, include, url
 from ratelimitbackend import admin
 from django.conf.urls.static import static
 
-# Not used, the work is done in the imported module.
-from . import one_time_startup      # pylint: disable=W0611
-
 import django.contrib.auth.views
 
 # Uncomment the next two lines to enable the admin:
diff --git a/lms/wsgi.py b/lms/wsgi.py
index 270b019addad94ac6c0d55badb31bf209ca9243d..683ef46892271b1e8d7b1e412fde8f6e183c5294 100644
--- a/lms/wsgi.py
+++ b/lms/wsgi.py
@@ -2,13 +2,11 @@ import os
 
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.envs.aws")
 
+import lms.startup as startup
+startup.run()
+
 # This application object is used by the development server
 # as well as any WSGI server configured to use this file.
 from django.core.wsgi import get_wsgi_application
 application = get_wsgi_application()
 
-from django.conf import settings
-from xmodule.modulestore.django import modulestore
-
-for store_name in settings.MODULESTORE:
-    modulestore(store_name)
diff --git a/manage.py b/manage.py
index ebaebe8b66f57b39778302083a250aadbf30ad57..a5c6e5fb2ba99015d6c3c5103c18a5b9fd496a0c 100755
--- a/manage.py
+++ b/manage.py
@@ -13,8 +13,7 @@ Any arguments not understood by this manage.py will be passed to django-admin.py
 
 import os
 import sys
-import glob2
-import imp
+import importlib
 from argparse import ArgumentParser
 
 def parse_args():
@@ -41,7 +40,8 @@ def parse_args():
     lms.set_defaults(
         help_string=lms.format_help(),
         settings_base='lms/envs',
-        default_settings='lms.envs.dev'
+        default_settings='lms.envs.dev',
+        startup='lms.startup',
     )
 
     cms = subparsers.add_parser(
@@ -59,7 +59,8 @@ def parse_args():
         help_string=cms.format_help(),
         settings_base='cms/envs',
         default_settings='cms.envs.dev',
-        service_variant='cms'
+        service_variant='cms',
+        startup='cms.startup',
     )
 
     edx_args, django_args = parser.parse_known_args()
@@ -86,6 +87,9 @@ if __name__ == "__main__":
         # This will trigger django-admin.py to print out its help
         django_args.append('--help')
 
+    startup = importlib.import_module(edx_args.startup)
+    startup.run()
+
     from django.core.management import execute_from_command_line
 
     execute_from_command_line([sys.argv[0]] + django_args)