diff --git a/djangoldp/permissions.py b/djangoldp/permissions.py
index 1d26706bfde5c8999bd8f7cd1bb6cc83d5754c05..bfbd3e94f3972cb1640d88d455c4dc9bda9e001f 100644
--- a/djangoldp/permissions.py
+++ b/djangoldp/permissions.py
@@ -30,7 +30,7 @@ class LDPPermissions(DjangoObjectPermissions):
 
     @classmethod
     def refresh_cache(cls):
-        if (time.time() - cls.perms_cache['time']) > 100:
+        if (time.time() - cls.perms_cache['time']) > 5:
             cls.invalidate_cache()
 
     def user_permissions(self, user, obj_or_model, obj=None):
diff --git a/djangoldp/serializers.py b/djangoldp/serializers.py
index 4d320001366f9109cd33a9e5913d8ea4c10c5c6e..3dad3bed765ea96d94d6ecf01faff2ba4ebecbd6 100644
--- a/djangoldp/serializers.py
+++ b/djangoldp/serializers.py
@@ -1,24 +1,25 @@
-import time
 import uuid
 from collections import OrderedDict, Mapping, Iterable
 from typing import Any
 from urllib import parse
 
+import time
 from django.conf import settings
 from django.contrib.auth import get_user_model
 from django.core.exceptions import ImproperlyConfigured
 from django.core.exceptions import ValidationError as DjangoValidationError
 from django.db import transaction
+from django.db.models import QuerySet
 from django.urls import resolve, Resolver404, get_script_prefix
 from django.urls.resolvers import get_resolver
-from django.db.models import QuerySet
 from django.utils.datastructures import MultiValueDictKeyError
 from django.utils.encoding import uri_to_iri
 from rest_framework.exceptions import ValidationError
 from rest_framework.fields import SkipField, empty, ReadOnlyField
 from rest_framework.fields import get_error_detail, set_value
 from rest_framework.relations import HyperlinkedRelatedField, ManyRelatedField, MANY_RELATION_KWARGS, Hyperlink
-from rest_framework.serializers import HyperlinkedModelSerializer, ListSerializer, ModelSerializer, LIST_SERIALIZER_KWARGS
+from rest_framework.serializers import HyperlinkedModelSerializer, ListSerializer, ModelSerializer, \
+    LIST_SERIALIZER_KWARGS
 from rest_framework.settings import api_settings
 from rest_framework.utils import model_meta
 from rest_framework.utils.field_mapping import get_nested_relation_kwargs
@@ -31,28 +32,31 @@ from djangoldp.permissions import LDPPermissions
 
 class InMemoryCache:
 
-    def __init__(self):
+    def __init__(self, max_age=300):
+        self.max_age = max_age
         self.cache = {
-            'time': time.time()
         }
 
-    def invalidate_cache(self):
+    def reset(self):
         self.cache = {
-            'time': time.time()
         }
 
-    def refresh_cache(self):
-        if (time.time() - self.cache['time']) > 300:
-            self.invalidate_cache()
-
     def has(self, cache_key):
-        return cache_key in self.cache
+        if cache_key in self.cache:
+            if time.time() - self.cache[cache_key]['time'] < self.max_age:
+                return True
+            else:
+                self.invalidate(cache_key)
+        return False
 
     def get(self, cache_key):
-        return self.cache[cache_key]
+        return self.cache[cache_key]['value']
 
     def set(self, cache_key, value):
-        self.cache[cache_key] = value
+        self.cache[cache_key] = {'time': time.time(), 'value': value}
+
+    def invalidate(self, cache_key):
+        self.cache.pop(cache_key, None)
 
 
 class LDListMixin:
@@ -88,7 +92,6 @@ class LDListMixin:
          - Can Add if add permission on contained object's type
          - Can view the container is view permission on container model : container obj are filtered by view permission
         '''
-        self.to_representation_cache.refresh_cache()
         try:
             child_model = getattr(self, self.child_attr).Meta.model
         except AttributeError:
@@ -133,10 +136,10 @@ class LDListMixin:
                 Model.get_permissions(parent_model, self.context, ['view']))
 
         self.to_representation_cache.set(self.id, {'@id': self.id,
-                '@type': 'ldp:Container',
-                'ldp:contains': super().to_representation(filtered_values),
-                'permissions': container_permissions
-                })
+                                                   '@type': 'ldp:Container',
+                                                   'ldp:contains': super().to_representation(filtered_values),
+                                                   'permissions': container_permissions
+                                                   })
 
         return self.to_representation_cache.get(self.id)
 
@@ -262,6 +265,7 @@ class JsonLdRelatedField(JsonLdField):
 
 class JsonLdIdentityField(JsonLdField):
     '''Represents an identity (url) field for a serializer'''
+
     def __init__(self, view_name=None, **kwargs):
         kwargs['read_only'] = True
         kwargs['source'] = '*'
@@ -317,7 +321,6 @@ class LDPSerializer(HyperlinkedModelSerializer):
 
     def to_representation(self, obj):
         # external Models should only be returned with an id (on GET)
-        self.to_representation_cache.refresh_cache()
         if self.context['request'].method == 'GET' and Model.is_external(obj):
             return {'@id': obj.urlid}
 
@@ -591,6 +594,7 @@ class LDPSerializer(HyperlinkedModelSerializer):
     def create(self, validated_data):
         with transaction.atomic():
             instance = self.internal_create(validated_data, model=self.Meta.model)
+            LDListMixin.to_representation_cache.invalidate('{}{}'.format(settings.BASE_URL, Model.resource(self.Meta.model)))
             self.attach_related_object(instance, validated_data)
 
         return instance
@@ -660,6 +664,11 @@ class LDPSerializer(HyperlinkedModelSerializer):
 
         self.save_or_update_nested_list(instance, nested_fields)
         instance.save()
+        resource_path = Model.resource(self.Meta.model)
+        LDListMixin.to_representation_cache.invalidate('{}{}'.format(settings.BASE_URL, resource_path))
+        LDPSerializer.to_representation_cache.invalidate('{}{}'.format(settings.BASE_URL, resource_path))
+        LDListMixin.to_representation_cache.invalidate('{}{}{}'.format(settings.BASE_URL, resource_path, instance.id))
+        LDPSerializer.to_representation_cache.invalidate('{}{}{}'.format(settings.BASE_URL, resource_path, instance.id))
 
         return instance
 
@@ -710,7 +719,7 @@ class LDPSerializer(HyperlinkedModelSerializer):
         info = model_meta.get_field_info(instance)
         slug_field = Model.slug_field(instance)
         relation_info = info.relations.get(attr)
-        if slug_field in value :
+        if slug_field in value:
             value = self.update_dict_value_when_id_is_provided(attr, instance, relation_info, slug_field, value)
         else:
             if 'urlid' in value:
diff --git a/djangoldp/tests/perf_result.csv b/djangoldp/tests/perf_result.csv
index 33d2f033490923f81080c5ac54527b537eb97bb3..c6281b8e0e6b9326faa9c8451eaf3f71d72037b9 100644
--- a/djangoldp/tests/perf_result.csv
+++ b/djangoldp/tests/perf_result.csv
@@ -46,4 +46,6 @@ jbl+AC0-T440p,Oct 09 2020 11:56:19,True,True,100,0.003119325637817,0.00560247182
 jbl+AC0-T440p,Oct 09 2020 11:58:22,True,True,100,0.003008058071136,0.005401248931885,0.010658957958222,0.003909242153168,0.000718443393707,0.301162958145142,TRUE,3
 jbl+AC0-T440p,Oct 09 2020 11:59:16,True,True,100,0.003015418052673,0.005526115894318,0.010740044116974,0.00400491476059,0.000724492073059,0.313828229904175,TRUE,4
 jbl+AC0-T440p,Oct 09 2020 12:00:32,True,True,100,0.002969658374786,0.005434756278992,0.018136837482452,0.003030817508698,0.000726938247681,0.320115327835083,TRUE,0
-jbl-T440p,Oct 09 2020 12:21:00,True,True,100,0.0034934663772583007,0.0061032938957214355,0.019232537746429443,0.003091294765472412,0.0007375502586364747,0.36986708641052246,N/A
+jbl+AC0-T440p,Oct 09 2020 12:21:00,True,True,100,0.003493466377258,0.006103293895721,0.01923253774643,0.003091294765472,0.000737550258636,0.369867086410522,TRUE,0
+jbl+AC0-T440p,Oct 15 2020 22:00:10,True,True,100,0.003004941940308,0.00546817779541,0.018348352909088,0.003068554401398,0.000729415416718,0.320573329925537,TRUE,0
+jbl+AC0-T440p,Oct 15 2020 22:15:26,True,True,100,0.003350086212158,0.005898218154907,0.011625332832337,0.004264788627625,0.000795011520386,0.319289922714233,TRUE,1
diff --git a/djangoldp/tests/runner.py b/djangoldp/tests/runner.py
index 3966fd5190de0a9f37e7c3838f15e24b2c234e62..7113ac4be827069510bf0aa2fccec5f19b11c134 100644
--- a/djangoldp/tests/runner.py
+++ b/djangoldp/tests/runner.py
@@ -24,7 +24,8 @@ failures = test_runner.run_tests([
     'djangoldp.tests.tests_sources',
     'djangoldp.tests.tests_pagination',
     'djangoldp.tests.tests_inbox',
-    'djangoldp.tests.tests_backlinks_service'
+    'djangoldp.tests.tests_backlinks_service',
+    'djangoldp.tests.tests_cache'
 
 ])
 if failures:
diff --git a/djangoldp/tests/tests_cache.py b/djangoldp/tests/tests_cache.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff4aed657bae7be0b803a4b863e2add45fb52d56
--- /dev/null
+++ b/djangoldp/tests/tests_cache.py
@@ -0,0 +1,73 @@
+from django.contrib.auth import get_user_model
+from django.test import TestCase
+from rest_framework.test import APIRequestFactory, APIClient
+from rest_framework.utils import json
+
+from djangoldp.models import Model
+from djangoldp.serializers import LDPSerializer, LDListMixin
+from djangoldp.tests.models import Skill, JobOffer, Invoice, LDPDummy, Resource, Post, Circle, Project, Conversation
+
+
+class TestCache(TestCase):
+
+    def setUp(self):
+        self.factory = APIRequestFactory()
+        self.client = APIClient()
+        self.user = get_user_model().objects.create_user(username='john', email='jlennon@beatles.com',
+                                                         password='glass onion')
+        self.client.force_authenticate(self.user)
+        LDListMixin.to_representation_cache.reset()
+        LDPSerializer.to_representation_cache.reset()
+
+    def tearDown(self):
+        pass
+
+    def test_save_fk_graph_with_nested(self):
+        response = self.client.get('/batchs/', content_type='application/ld+json')
+        self.assertEqual(response.status_code, 200)
+
+        post = {
+            '@graph': [
+                {
+                    'http://happy-dev.fr/owl/#title': "title",
+                    'http://happy-dev.fr/owl/#invoice': {
+                        '@id': "_.123"
+                    }
+                },
+                {
+                    '@id': "_.123",
+                    'http://happy-dev.fr/owl/#title': "title 2"
+                }
+            ]
+        }
+
+        response = self.client.post('/batchs/', data=json.dumps(post), content_type='application/ld+json')
+        self.assertEqual(response.status_code, 201)
+
+        response = self.client.get('/batchs/', content_type='application/ld+json')
+        self.assertIn('ldp:contains', response.data)
+        self.assertEquals(response.data['ldp:contains'][0]['title'], "title")
+        self.assertEquals(response.data['ldp:contains'][0]['invoice']['title'], "title 2")
+
+    def test_update_with_new_fk_relation(self):
+        conversation = Conversation.objects.create(author_user=self.user,
+                                                   description="conversation description")
+        response = self.client.get('/conversations/{}/'.format(conversation.pk), content_type='application/ld+json')
+        body = [
+            {
+                '@id': "/conversations/{}/".format(conversation.pk),
+                'http://happy-dev.fr/owl/#description': "conversation update",
+                'http://happy-dev.fr/owl/#peer_user': {
+                    '@id': 'http://happy-dev.fr/users/{}'.format(self.user.pk),
+                }
+            }
+        ]
+        response = self.client.put('/conversations/{}/'.format(conversation.pk), data=json.dumps(body),
+                                   content_type='application/ld+json')
+        self.assertEqual(response.status_code, 200)
+
+        response = self.client.get('/conversations/{}/'.format(conversation.pk), content_type='application/ld+json')
+        self.assertIn('peer_user', response.data)
+        self.assertEquals('conversation update', response.data['description'])
+        self.assertIn('@id', response.data['peer_user'])
+
diff --git a/djangoldp/tests/tests_get.py b/djangoldp/tests/tests_get.py
index 5e93f212ee7411bb9e1262674a1a4c9b240f8828..be8e5b19179f36fe7d728333e74d136ddcf040aa 100644
--- a/djangoldp/tests/tests_get.py
+++ b/djangoldp/tests/tests_get.py
@@ -11,8 +11,8 @@ class TestGET(APITestCase):
     def setUp(self):
         self.factory = APIRequestFactory()
         self.client = APIClient()
-        LDListMixin.to_representation_cache.invalidate_cache()
-        LDPSerializer.to_representation_cache.invalidate_cache()
+        LDListMixin.to_representation_cache.reset()
+        LDPSerializer.to_representation_cache.reset()
 
     def tearDown(self):
         pass
diff --git a/djangoldp/tests/tests_save.py b/djangoldp/tests/tests_save.py
index 7a7dbeb3b9059be91bde8ae3127c5a48a6dfa63c..afd624e4e118a1b8489430b515c2e28e5fa3e0b7 100644
--- a/djangoldp/tests/tests_save.py
+++ b/djangoldp/tests/tests_save.py
@@ -16,8 +16,8 @@ class Save(TestCase):
         self.user = get_user_model().objects.create_user(username='john', email='jlennon@beatles.com',
                                                          password='glass onion')
         self.client.force_authenticate(self.user)
-        LDListMixin.to_representation_cache.invalidate_cache()
-        LDPSerializer.to_representation_cache.invalidate_cache()
+        LDListMixin.to_representation_cache.reset()
+        LDPSerializer.to_representation_cache.reset()
 
     def tearDown(self):
         pass
diff --git a/djangoldp/tests/tests_update.py b/djangoldp/tests/tests_update.py
index ea293c3a4118af7889fcca3224e71e66002b88a7..a4b6ef01f8d0351be43322f36c9e1badba4dc873 100644
--- a/djangoldp/tests/tests_update.py
+++ b/djangoldp/tests/tests_update.py
@@ -17,8 +17,8 @@ class Update(TestCase):
         self.user = get_user_model().objects.create_user(username='john', email='jlennon@beatles.com',
                                                          password='glass onion')
         self.client.force_authenticate(user=self.user)
-        LDListMixin.to_representation_cache.invalidate_cache()
-        LDPSerializer.to_representation_cache.invalidate_cache()
+        LDListMixin.to_representation_cache.reset()
+        LDPSerializer.to_representation_cache.reset()
 
     def tearDown(self):
         pass