diff --git a/biscuit/apps/chronos/forms.py b/biscuit/apps/chronos/forms.py
index 638b6d3569bb174bf1bf8e6504099b4e7559113d..08a1c5c21341380e9efdf9f7938bb51f91c71125 100644
--- a/biscuit/apps/chronos/forms.py
+++ b/biscuit/apps/chronos/forms.py
@@ -24,4 +24,4 @@ class SelectForm(forms.Form):
 class LessonSubstitutionForm(forms.ModelForm):
     class Meta:
         model = LessonSubstitution
-        fields = ['week', 'lesson_period', 'subject', 'teachers', 'room']
+        fields = ['week', 'lesson_period', 'subject', 'teachers', 'room', 'cancelled']
diff --git a/biscuit/apps/chronos/migrations/0003_auto_20190907_1419.py b/biscuit/apps/chronos/migrations/0003_auto_20190907_1419.py
new file mode 100644
index 0000000000000000000000000000000000000000..7f53974affeec61b9164028cfa3b4447345aae5c
--- /dev/null
+++ b/biscuit/apps/chronos/migrations/0003_auto_20190907_1419.py
@@ -0,0 +1,22 @@
+# Generated by Django 2.2.5 on 2019-09-07 14:19
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('chronos', '0002_db_indexes'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='lessonsubstitution',
+            name='cancelled',
+            field=models.BooleanField(default=False),
+        ),
+        migrations.AddConstraint(
+            model_name='lessonsubstitution',
+            constraint=models.CheckConstraint(check=models.Q(('cancelled', True), ('subject__isnull', False), _negated=True), name='either_substituted_or_cancelled'),
+        ),
+    ]
diff --git a/biscuit/apps/chronos/models.py b/biscuit/apps/chronos/models.py
index e1100d0c0c0fb45a9ad4c95796579c7b2a518e9f..9a5d529038dac514076f0334f07e7dce626e1e1a 100644
--- a/biscuit/apps/chronos/models.py
+++ b/biscuit/apps/chronos/models.py
@@ -2,7 +2,9 @@ from datetime import datetime
 from typing import Dict, Optional, Tuple
 
 from django.core import validators
+from django.core.exceptions import ValidationError
 from django.db import models
+from django.db.models import Q
 from django.utils.translation import ugettext_lazy as _
 
 from biscuit.core.mixins import SchoolRelated
@@ -119,10 +121,22 @@ class LessonSubstitution(SchoolRelated):
                                       related_name='lesson_substitutions')
     room = models.ForeignKey('Room', models.CASCADE, null=True)
 
+    cancelled = models.BooleanField(default=False)
+
+    def clean(self) -> None:
+        if self.subject and self.cancelled:
+            raise ValidationError(_('Lessons can only be either substituted or cancelled.'))
+
     class Meta:
         unique_together = [['school', 'lesson_period', 'week']]
         ordering = ['lesson_period__lesson__date_start', 'week',
                     'lesson_period__period__weekday', 'lesson_period__period__period']
+        constraints = [
+            models.CheckConstraint(
+                check=~Q(cancelled=True, subject__isnull=False),
+                name='either_substituted_or_cancelled'
+            )
+        ]
 
 
 class LessonPeriod(SchoolRelated):
diff --git a/biscuit/apps/chronos/static/css/chronos/timetable.css b/biscuit/apps/chronos/static/css/chronos/timetable.css
index 6d7a5af706b33e4bc81958ada4acd360f759a43c..eb0ed9a984d776e326a9bbe56ae09d6b279ee248 100644
--- a/biscuit/apps/chronos/static/css/chronos/timetable.css
+++ b/biscuit/apps/chronos/static/css/chronos/timetable.css
@@ -5,4 +5,9 @@
 ul#timetable_select_form li {
     dispaly: inline;
 
-}
\ No newline at end of file
+}
+
+.chronos-lesson-cancelled {
+    background-color: inherit !important;
+    text-decoration: line-through;
+}
diff --git a/biscuit/apps/chronos/templates/chronos/tt_lesson.html b/biscuit/apps/chronos/templates/chronos/tt_lesson.html
index f7a3028fe133f035f3b2ae52de0a40c828db3e4f..cf2c15b584b7c16c49db960d3c8a39f0f3a0c3c3 100644
--- a/biscuit/apps/chronos/templates/chronos/tt_lesson.html
+++ b/biscuit/apps/chronos/templates/chronos/tt_lesson.html
@@ -1,8 +1,10 @@
 {# -*- engine:django -*- #}
 
 <div class="card chronos-lesson
-  {% if lesson_period.get_substitution %}
-  border border-warning
+  {% if lesson_period.get_substitution.cancelled %}
+    border border-danger chronos-lesson-cancelled
+  {% elif lesson_period.get_substitution %}
+    border border-warning
   {% endif %}
   "
   style="