diff --git a/ldvspec/lofardata/migrations/0017_group_workspecification_group.py b/ldvspec/lofardata/migrations/0017_group_workspecification_group.py
new file mode 100644
index 0000000000000000000000000000000000000000..ab223044d9df0ddef5ac0fea65693f45909f77af
--- /dev/null
+++ b/ldvspec/lofardata/migrations/0017_group_workspecification_group.py
@@ -0,0 +1,30 @@
+# Generated by Django 4.1.5 on 2023-01-19 09:17
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('lofardata', '0016_alter_workspecification_inputs_and_more'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Group',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=50, unique=True)),
+                ('selected_workflow', models.CharField(blank=True, default='', max_length=500)),
+                ('selected_workflow_tag', models.CharField(blank=True, default='', max_length=500)),
+                ('processing_site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='lofardata.atdbprocessingsite')),
+                ('work_specifications', models.ManyToManyField(blank=True, related_name='+', to='lofardata.workspecification')),
+            ],
+        ),
+        migrations.AddField(
+            model_name='workspecification',
+            name='group',
+            field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, to='lofardata.group'),
+        ),
+    ]
diff --git a/ldvspec/lofardata/models.py b/ldvspec/lofardata/models.py
index 7d32716802c0f0525ac313e52b6de24ad02a4dd3..80d448cb5a658868ed2f781d2978d30400b3d12c 100644
--- a/ldvspec/lofardata/models.py
+++ b/ldvspec/lofardata/models.py
@@ -4,6 +4,7 @@ from django.contrib.auth.models import User
 from django.contrib.postgres.fields import ArrayField
 from django.db import models, IntegrityError
 from django.utils.translation import gettext_lazy as _
+
 logger = logging.getLogger(__name__)
 
 
@@ -109,11 +110,25 @@ class PURGE_POLICY(models.TextChoices):
     DO = "do", _("do")  # only purge, no workflow execution
 
 
+class Group(models.Model):
+    """Group to which work specification belongs"""
+
+    name = models.CharField(max_length=50, unique=True)
+    work_specifications = models.ManyToManyField('WorkSpecification', blank=True, related_name='+')
+    # ATDB info
+    processing_site = models.ForeignKey(ATDBProcessingSite, null=True, blank=True, on_delete=models.SET_NULL)
+    selected_workflow = models.CharField(max_length=500, blank=True, default='')
+    selected_workflow_tag = models.CharField(max_length=500, blank=True, default='')
+
+
 class WorkSpecification(models.Model):
     """Work Specification"""
 
     created_on = models.DateTimeField(auto_now_add=True)
     created_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, null=True)
+
+    group = models.ForeignKey(Group, null=True, default=None, on_delete=models.SET_DEFAULT)
+
     filters = models.JSONField(null=True)
     # Input data containing sizes/urls for submission to ATDB
     inputs = models.JSONField(null=True, blank=True)