diff --git a/.circleci/config.yml b/.circleci/config.yml
index 605052d3d2007551ba31c50f48cc7c2bddbea88e..9acb5cfa8f551d7bd0584f8e91d395b2b5cf1ddd 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -77,6 +77,6 @@ jobs:
             flake8 ./opentech
             python manage.py collectstatic --noinput --verbosity=0
             python manage.py check
-            python manage.py makemigrations --check --noinput --verbosity=0
+            python manage.py makemigrations --check --noinput --verbosity=1
             coverage run --source='opentech' manage.py test
             codecov
diff --git a/opentech/apply/activity/messaging.py b/opentech/apply/activity/messaging.py
index 23b11f271f97a7fa9cf5fcb00dfb34ee0730a835..29c0ad9d865174320b45a13d5f8f5c2f5f73aa4a 100644
--- a/opentech/apply/activity/messaging.py
+++ b/opentech/apply/activity/messaging.py
@@ -225,19 +225,44 @@ class SlackAdapter(AdapterBase):
             return f'<{user.slack}>'
         return ''
 
+    def slack_channel(self, submission):
+        try:
+            target_room = submission.get_from_parent('slack_channel')
+        except AttributeError:
+            # If not a submission object, set room to default.
+            target_room = self.target_room
+        else:
+            if not target_room:
+                # If no custom room, set to default.
+                target_room = self.target_room
+
+        # Make sure the channel name starts with a "#".
+        if target_room and not target_room.startswith('#'):
+            target_room = f"#{target_room}"
+
+        return target_room
+
     def send_message(self, message, recipient, **kwargs):
-        if not self.destination or not self.target_room:
+        try:
+            submission = kwargs['submission']
+        except Exception:
+            # If no submission, set room to default.
+            target_room = self.target_room
+        else:
+            target_room = self.slack_channel(submission)
+
+        if not self.destination or not target_room:
             errors = list()
             if not self.destination:
                 errors.append('Destination URL')
-            if not self.target_room:
+            if not target_room:
                 errors.append('Room ID')
             return 'Missing configuration: {}'.format(', '.join(errors))
 
         message = ' '.join([recipient, message]).strip()
 
         data = {
-            "room": self.target_room,
+            "room": target_room,
             "message": message,
         }
         response = requests.post(self.destination, json=data)
diff --git a/opentech/apply/activity/tests/test_messaging.py b/opentech/apply/activity/tests/test_messaging.py
index aa07fb2da609f1eb71aa19b27bfa9ddb4a3d3b53..ec782ecf9cbf2f567b2e96db42c0b513dc17271d 100644
--- a/opentech/apply/activity/tests/test_messaging.py
+++ b/opentech/apply/activity/tests/test_messaging.py
@@ -225,7 +225,7 @@ class TestActivityAdapter(TestCase):
 
 class TestSlackAdapter(AdapterMixin, TestCase):
     target_url = 'https://my-slack-backend.com/incoming/my-very-secret-key'
-    target_room = '<ROOM ID>'
+    target_room = '#<ROOM ID>'
 
     @override_settings(
         SLACK_DESTINATION_URL=target_url,
diff --git a/opentech/apply/funds/migrations/0048_add_field_slack_channel.py b/opentech/apply/funds/migrations/0048_add_field_slack_channel.py
new file mode 100644
index 0000000000000000000000000000000000000000..328a04eed01698c515572b22e55866fec160d902
--- /dev/null
+++ b/opentech/apply/funds/migrations/0048_add_field_slack_channel.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.0.9 on 2019-01-14 12:26
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('funds', '0047_add_markdown'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='applicationbase',
+            name='slack_channel',
+            field=models.CharField(blank=True, help_text='The slack #channel for notifications.', max_length=128),
+        ),
+        migrations.AddField(
+            model_name='labbase',
+            name='slack_channel',
+            field=models.CharField(blank=True, help_text='The slack #channel for notifications.', max_length=128),
+        ),
+    ]
diff --git a/opentech/apply/funds/models/applications.py b/opentech/apply/funds/models/applications.py
index 01a754b170c50fa9616b622ee9e1b0e3bbbb80d6..0119e8c6503b93503336affddad338f2fd37ba3c 100644
--- a/opentech/apply/funds/models/applications.py
+++ b/opentech/apply/funds/models/applications.py
@@ -7,6 +7,7 @@ from django.db.models import OuterRef, Q, Subquery
 from django.http import Http404
 from django.utils.functional import cached_property
 from django.utils.text import mark_safe
+from django.utils.translation import ugettext_lazy as _
 
 from modelcluster.fields import ParentalManyToManyField
 
@@ -48,6 +49,8 @@ class ApplicationBase(EmailForm, WorkflowStreamForm):  # type: ignore
         blank=True,
     )
 
+    slack_channel = models.CharField(blank=True, max_length=128, help_text=_('The slack #channel for notifications.'))
+
     objects = PageManager.from_queryset(ApplicationBaseManager)()
 
     parent_page_types = ['apply_home.ApplyHomePage']
@@ -82,6 +85,7 @@ class ApplicationBase(EmailForm, WorkflowStreamForm):  # type: ignore
 
     content_panels = WorkflowStreamForm.content_panels + [
         FieldPanel('reviewers'),
+        FieldPanel('slack_channel'),
     ]
 
     edit_handler = TabbedInterface([
@@ -280,12 +284,15 @@ class LabBase(EmailForm, WorkflowStreamForm, SubmittableStreamForm):  # type: ig
         blank=True,
     )
 
+    slack_channel = models.CharField(blank=True, max_length=128, help_text=_('The slack #channel for notifications.'))
+
     parent_page_types = ['apply_home.ApplyHomePage']
     subpage_types = []  # type: ignore
 
     content_panels = WorkflowStreamForm.content_panels + [
         FieldPanel('lead'),
         FieldPanel('reviewers'),
+        FieldPanel('slack_channel'),
     ]
 
     edit_handler = TabbedInterface([