diff --git a/affiliations/admin.py b/affiliations/admin.py
index 7d69fafdbd7a4a548ded801972c0279ec1bc0ce0..c5caa196a71f9055181c39f64ce325781942d563 100644
--- a/affiliations/admin.py
+++ b/affiliations/admin.py
@@ -1,6 +1,7 @@
 from django.contrib import admin
 
-from .models import Institute
+from .models import Affiliation, Institute
 
 
+admin.site.register(Affiliation)
 admin.site.register(Institute)
diff --git a/affiliations/migrations/0005_affiliation.py b/affiliations/migrations/0005_affiliation.py
new file mode 100644
index 0000000000000000000000000000000000000000..7d4a84394dd3b11b752ff9295448beae27837c0a
--- /dev/null
+++ b/affiliations/migrations/0005_affiliation.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-11-02 07:41
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('scipost', '0069_auto_20171102_0840'),
+        ('affiliations', '0004_auto_20171101_2208'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Affiliation',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('begin_date', models.DateField(blank=True, null=True)),
+                ('end_date', models.DateField(blank=True, null=True)),
+                ('contributor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='affiliations', to='scipost.Contributor')),
+                ('institute', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='affiliations', to='affiliations.Institute')),
+            ],
+            options={
+                'default_related_name': 'affiliations',
+            },
+        ),
+    ]
diff --git a/affiliations/migrations/0006_auto_20171102_0843.py b/affiliations/migrations/0006_auto_20171102_0843.py
new file mode 100644
index 0000000000000000000000000000000000000000..bf8745a366ed9df5067bb99ca24254415596790f
--- /dev/null
+++ b/affiliations/migrations/0006_auto_20171102_0843.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-11-02 07:43
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+def fill_affiliations(apps, schema_editor):
+    Contributor = apps.get_model('scipost', 'Contributor')
+    Affiliation = apps.get_model('affiliations', 'Affiliation')
+    for contributor in Contributor.objects.all():
+        Affiliation.objects.get_or_create(
+            institute=contributor.old_affiliation_fk, contributor=contributor)
+
+
+def return_none(*args, **kwargs):
+    return
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('affiliations', '0005_affiliation'),
+    ]
+
+    operations = [
+        migrations.RunPython(fill_affiliations, return_none),
+    ]
diff --git a/affiliations/models.py b/affiliations/models.py
index feb9bd1d060374fa357ed5060d101f6cea4ee836..edbd131b7edc5117c8e2c9911b62644d73182699 100644
--- a/affiliations/models.py
+++ b/affiliations/models.py
@@ -12,16 +12,33 @@ class Institute(models.Model):
     """
     name = models.CharField(max_length=255)
     acronym = models.CharField(max_length=16, blank=True)
-    # address = models.TextField(blank=True)
     country = CountryField()
     type = models.CharField(max_length=16, choices=INSTITUTE_TYPES, default=TYPE_UNIVERSITY)
 
     class Meta:
-        default_related_name = 'affiliations'
+        default_related_name = 'institutes'
         ordering = ['country']
 
     def __str__(self):
         return '{name} ({country})'.format(name=self.name, country=self.get_country_display())
 
     def get_absolute_url(self):
-        return reverse('affiliations:affiliation_details', args=(self.id,))
+        return reverse('affiliations:institute_details', args=(self.id,))
+
+
+class Affiliation(models.Model):
+    """
+    An Affiliation is a (time dependent) connection between an Institute and a Contributor.
+    This could thus be changed over time and history will be preserved.
+    """
+    institute = models.ForeignKey('affiliations.Institute')
+    contributor = models.ForeignKey('scipost.Contributor')
+    begin_date = models.DateField(null=True, blank=True)
+    end_date = models.DateField(null=True, blank=True)
+
+    class Meta:
+        default_related_name = 'affiliations'
+
+    def __str__(self):
+        return '{contributor} ({institute})'.format(
+            contributor=self.contributor, institute=self.institute.name)
diff --git a/scipost/migrations/0069_auto_20171102_0840.py b/scipost/migrations/0069_auto_20171102_0840.py
new file mode 100644
index 0000000000000000000000000000000000000000..1de2b91a9358bde40dc595dd50e8484e6f89841c
--- /dev/null
+++ b/scipost/migrations/0069_auto_20171102_0840.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-11-02 07:40
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('scipost', '0068_auto_20171101_2132'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='contributor',
+            old_name='affiliation',
+            new_name='old_affiliation_fk',
+        ),
+    ]
diff --git a/scipost/migrations/0070_remove_contributor_old_affiliation_fk.py b/scipost/migrations/0070_remove_contributor_old_affiliation_fk.py
new file mode 100644
index 0000000000000000000000000000000000000000..01a7bf2698a49cb00331d27fb633a29c7301fcdb
--- /dev/null
+++ b/scipost/migrations/0070_remove_contributor_old_affiliation_fk.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2017-11-02 07:55
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('affiliations', '0006_auto_20171102_0843'),
+        ('scipost', '0069_auto_20171102_0840'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='contributor',
+            name='old_affiliation_fk',
+        ),
+    ]
diff --git a/scipost/models.py b/scipost/models.py
index 0fdd695cf594644929a243bbd9539451ae7a3554..eec7395d1414998a8a4cc6aafac8eb4dd5e620c9 100644
--- a/scipost/models.py
+++ b/scipost/models.py
@@ -50,10 +50,6 @@ class Contributor(models.Model):
         blank=True, null=True)
     orcid_id = models.CharField(max_length=20, verbose_name="ORCID id",
                                 blank=True)
-    old_country_of_employment = CountryField()
-    old_affiliation = models.CharField(max_length=300, verbose_name='affiliation')
-    affiliation = models.ForeignKey('affiliations.Institute', null=True, blank=True,
-                                    related_name='contributors')
     address = models.CharField(max_length=1000, verbose_name="address",
                                blank=True)
     personalwebpage = models.URLField(verbose_name='personal web page',
@@ -65,6 +61,10 @@ class Contributor(models.Model):
         default=True,
         verbose_name="I accept to receive SciPost emails")
 
+    # U/S
+    old_country_of_employment = CountryField()
+    old_affiliation = models.CharField(max_length=300, verbose_name='affiliation')
+
     objects = ContributorManager()
 
     def __str__(self):