diff --git a/src/dispatch/case/flows.py b/src/dispatch/case/flows.py
index 22c511159bc1..dca97232bd0e 100644
--- a/src/dispatch/case/flows.py
+++ b/src/dispatch/case/flows.py
@@ -535,7 +535,7 @@ def case_status_transition_flow_dispatcher(
             )
 
         case (_, CaseStatus.triage):
-            # Any -> Triage
+            # Any -> Triage/
             pass
 
         case (CaseStatus.new, CaseStatus.escalated):
diff --git a/src/dispatch/database/revisions/tenant/versions/2024-05-29_a836d4850a75.py b/src/dispatch/database/revisions/tenant/versions/2024-05-29_a836d4850a75.py
new file mode 100644
index 000000000000..8661fb076e09
--- /dev/null
+++ b/src/dispatch/database/revisions/tenant/versions/2024-05-29_a836d4850a75.py
@@ -0,0 +1,27 @@
+"""Adding in "allow_self_join" column to enable self join in dispatch UI
+
+Revision ID: a836d4850a75
+Revises: b07bb852fd67
+Create Date: 2024-04-29 10:28:37.777618
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+# revision identifiers, used by Alembic.
+revision = 'a836d4850a75'
+down_revision = 'b07bb852fd67'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.add_column('project', sa.Column('allow_self_join', sa.Boolean(), server_default='t', nullable=True))
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    op.drop_column('project', 'allow_self_join')
+    # ### end Alembic commands ###
diff --git a/src/dispatch/incident/models.py b/src/dispatch/incident/models.py
index 78ea0495173c..0e932878f267 100644
--- a/src/dispatch/incident/models.py
+++ b/src/dispatch/incident/models.py
@@ -243,6 +243,7 @@ class ProjectRead(DispatchBase):
     name: NameStr
     color: Optional[str]
     stable_priority: Optional[IncidentPriorityRead] = None
+    allow_self_join: Optional[bool] = Field(True, nullable=True)
 
 
 class CaseRead(DispatchBase):
diff --git a/src/dispatch/project/models.py b/src/dispatch/project/models.py
index 61020475bcea..f42065333f24 100644
--- a/src/dispatch/project/models.py
+++ b/src/dispatch/project/models.py
@@ -40,6 +40,7 @@ class Project(Base):
     )
 
     enabled = Column(Boolean, default=True, server_default="t")
+    allow_self_join = Column(Boolean, default=True, server_default="t")
 
     send_daily_reports = Column(Boolean)
 
@@ -71,6 +72,7 @@ class ProjectBase(DispatchBase):
     color: Optional[str] = Field(None, nullable=True)
     send_daily_reports: Optional[bool] = Field(True, nullable=True)
     enabled: Optional[bool] = Field(True, nullable=True)
+    allow_self_join: Optional[bool] = Field(True, nullable=True)
 
 
 class ProjectCreate(ProjectBase):
diff --git a/src/dispatch/static/dispatch/src/incident/Table.vue b/src/dispatch/static/dispatch/src/incident/Table.vue
index 5c8de6bf3097..42f085b5b2aa 100644
--- a/src/dispatch/static/dispatch/src/incident/Table.vue
+++ b/src/dispatch/static/dispatch/src/incident/Table.vue
@@ -72,7 +72,11 @@
               <incident-priority :priority="value" />
             </template>
             <template #item.status="{ item, value }">
-              <incident-status :status="value" :id="item.id" />
+              <incident-status
+                :status="value"
+                :id="item.id"
+                :allowSelfJoin="item.project.allow_self_join"
+              />
             </template>
             <template #item.incident_costs="{ value }">
               <incident-cost-card :incident-costs="value" />
diff --git a/src/dispatch/static/dispatch/src/incident/status/IncidentStatus.vue b/src/dispatch/static/dispatch/src/incident/status/IncidentStatus.vue
index 1bbf4b7090e5..0cb6b65d5675 100644
--- a/src/dispatch/static/dispatch/src/incident/status/IncidentStatus.vue
+++ b/src/dispatch/static/dispatch/src/incident/status/IncidentStatus.vue
@@ -4,7 +4,7 @@
       {{ status }}
     </v-badge>
     <template v-if="status === 'Active' || status === 'Stable'">
-      <v-tooltip location="bottom" text="Join">
+      <v-tooltip location="bottom" text="Join" v-if="allowSelfJoin">
         <template #activator="{ props }">
           <v-btn
             v-bind="props"
@@ -46,6 +46,10 @@ export default {
       type: Number,
       required: true,
     },
+    allowSelfJoin: {
+      type: Boolean,
+      required: true,
+    },
   },
 
   computed: {
diff --git a/src/dispatch/static/dispatch/src/project/NewEditSheet.vue b/src/dispatch/static/dispatch/src/project/NewEditSheet.vue
index 0d40aae7260c..6d4f7803207b 100644
--- a/src/dispatch/static/dispatch/src/project/NewEditSheet.vue
+++ b/src/dispatch/static/dispatch/src/project/NewEditSheet.vue
@@ -59,6 +59,13 @@
                   hint="Whether this project is enabled for new cases and incidents."
                 />
               </v-col>
+              <v-col cols="12">
+                <v-checkbox
+                  v-model="allow_self_join"
+                  label="Allow Self Join"
+                  hint="Allow users to self-join an incident from the UI"
+                />
+              </v-col>
               <v-col cols="12">
                 <color-picker-input v-model="color" />
               </v-col>
@@ -152,6 +159,7 @@ export default {
       "selected.owner_conversation",
       "selected.owner_email",
       "selected.enabled",
+      "selected.allow_self_join",
       "dialogs.showCreateEdit",
     ]),
   },
diff --git a/src/dispatch/static/dispatch/src/project/store.js b/src/dispatch/static/dispatch/src/project/store.js
index bff2d8c81e24..e37376467c88 100644
--- a/src/dispatch/static/dispatch/src/project/store.js
+++ b/src/dispatch/static/dispatch/src/project/store.js
@@ -16,6 +16,7 @@ const getDefaultSelectedState = () => {
     owner_email: null,
     owner_conversation: null,
     enabled: null,
+    allow_self_join: null,
   }
 }