diff --git a/.circleci/config.yml b/.circleci/config.yml
index 5d1ba29917f4ab96e42e18e0a1bb8b3e8bcf83cc..c7e509566aa9c0e0e10654b6b9c6ff7a49a98a18 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -13,6 +13,7 @@ jobs:
           PGUSER: root
           DJANGO_SETTINGS_MODULE: opentech.settings.test
           SEND_MESSAGES: false
+          PROJECTS_ENABLED: true
 
       - image: circleci/postgres:10.5
         environment:
diff --git a/.travis.yml b/.travis.yml
index 3a9983e245c3b1b21cb284eeedf40771ddd90916..d2e18cf9fb607c1b6fb6e0318197728cc780363d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,6 +21,7 @@ env:
   global:
     - DJANGO_SETTINGS_MODULE=opentech.settings.test
     - DATABASE_URL=postgres://postgres@localhost/test_db
+    - PROJECTS_ENABLED=true
 
 before_script:
   # Create a database
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
index 49940120e0f2499ac37544762e5c4d3b5e3c70d9..2216c7cfc8e3a3a7ce11c3a373583fb3ce9ec754 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_admin_detail.html
@@ -17,7 +17,9 @@
         {% include "funds/includes/update_lead_form.html" %}
         {% include "funds/includes/update_reviewer_form.html" %}
         {% include "funds/includes/update_partner_form.html" %}
+        {% if settings.PROJECTS_ENABLED %}
         {% include "funds/includes/create_project_form.html" %}
+        {% endif %}
         {% include "funds/includes/update_meta_categories_form.html" %}
 {% endblock %}
 
diff --git a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
index 0583233d383fb2aaea67e4de8e36096900fa6d70..077f4ae6edf893c78a9d506c59426a52dcfaaef3 100644
--- a/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
+++ b/opentech/apply/funds/templates/funds/applicationsubmission_detail.html
@@ -99,7 +99,7 @@
                     {% endblock %}
                 {% endif %}
 
-                {% if object.project %}
+                {% if object.project and settings.PROJECTS_ENABLED %}
                     {% include 'funds/includes/project_block.html' %}
                 {% endif %}
 
diff --git a/opentech/apply/projects/models.py b/opentech/apply/projects/models.py
index c3fb3e4a6482f831cf2feb250a413251e1af5894..f13d8eed888c41d042667e89e66d4434baf19220 100644
--- a/opentech/apply/projects/models.py
+++ b/opentech/apply/projects/models.py
@@ -1,6 +1,7 @@
 import collections
 import decimal
 import json
+import logging
 
 from addressfield.fields import ADDRESS_FIELDS_ORDER
 from django.conf import settings
@@ -11,6 +12,8 @@ from django.db import models
 from django.urls import reverse
 from django.utils.translation import ugettext as _
 
+logger = logging.getLogger(__name__)
+
 
 class Approval(models.Model):
     project = models.ForeignKey("Project", on_delete=models.CASCADE, related_name="approvals")
@@ -118,6 +121,10 @@ class Project(models.Model):
         Returns a new Project or the given ApplicationSubmissions existing
         Project.
         """
+        if not settings.PROJECTS_ENABLED:
+            logging.error(f'Tried to create a Project for Submission ID={submission.id} while projects are disabled')
+            return None
+
         # OneToOne relations on the targetted model cannot be accessed without
         # an exception when the relation doesn't exist (is None).  Since we
         # want to fail fast here, we can use hasattr instead.
diff --git a/opentech/apply/projects/tests/test_settings.py b/opentech/apply/projects/tests/test_settings.py
new file mode 100644
index 0000000000000000000000000000000000000000..a627795b18231c015c2822138764dcb765fc82ad
--- /dev/null
+++ b/opentech/apply/projects/tests/test_settings.py
@@ -0,0 +1,15 @@
+from django.test import TestCase, override_settings
+
+from opentech.apply.users.tests.factories import StaffFactory
+
+
+class TestProjectFeatureFlag(TestCase):
+    @override_settings(PROJECTS_ENABLED=False)
+    def test_urls_404_when_turned_off(self):
+        self.client.force_login(StaffFactory())
+
+        response = self.client.get('/apply/projects/', follow=True)
+        self.assertEqual(response.status_code, 404)
+
+        response = self.client.get('/apply/projects/1/', follow=True)
+        self.assertEqual(response.status_code, 404)
diff --git a/opentech/apply/projects/urls.py b/opentech/apply/projects/urls.py
index ad585c9d1ed2664ad0ebe280470db602907ae9d1..d2d815129700cdad62ad19a2eed1ecc6ca45c902 100644
--- a/opentech/apply/projects/urls.py
+++ b/opentech/apply/projects/urls.py
@@ -1,10 +1,14 @@
+from django.conf import settings
 from django.urls import include, path
 
 from .views import ProjectDetailView, ProjectEditView
 
-urlpatterns = [
-    path('<int:pk>/', include([
-        path('', ProjectDetailView.as_view(), name='detail'),
-        path('edit/', ProjectEditView.as_view(), name="edit"),
-    ])),
-]
+urlpatterns = []
+
+if settings.PROJECTS_ENABLED:
+    urlpatterns = [
+        path('<int:pk>/', include([
+            path('', ProjectDetailView.as_view(), name='detail'),
+            path('edit/', ProjectEditView.as_view(), name="edit"),
+        ])),
+    ]
diff --git a/opentech/settings/base.py b/opentech/settings/base.py
index cff3aacacd8afaa2fe174e8e900c50f2f4ef0cca..6fa7c5852c2f38ecd3906c7fc7d1e5c2bd2a0775 100644
--- a/opentech/settings/base.py
+++ b/opentech/settings/base.py
@@ -668,3 +668,9 @@ REST_FRAMEWORK = {
         'rest_framework.permissions.IsAuthenticated',
     )
 }
+
+
+# Projects Feature Flag
+PROJECTS_ENABLED = False
+if env.get('PROJECTS_ENABLED', 'false').lower().strip() == 'true':
+    PROJECTS_ENABLED = True