diff --git a/src/GraphDeployer/HashUtil.cs b/src/GraphDeployer/HashUtil.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e2dbb73bfa42918afcf92fad7df5a02390748976
--- /dev/null
+++ b/src/GraphDeployer/HashUtil.cs
@@ -0,0 +1,18 @@
+using System.Security.Cryptography;
+
+namespace Coscine.GraphDeployer
+{
+    public static class HashUtil
+    {
+        public static string GetFileHash(string path)
+        {
+            using (SHA256 sha256 = SHA256.Create())
+            {
+                using (FileStream fileStream = File.OpenRead(path))
+                {
+                    return BitConverter.ToString(sha256.ComputeHash(fileStream));
+                }
+            }
+        }
+    }
+}
diff --git a/src/GraphDeployer/Program.cs b/src/GraphDeployer/Program.cs
index 7190b847586fb0e15c3c872bbceda32175a2d985..41489c4ab4457b4bc676bce603865dca890cc993 100644
--- a/src/GraphDeployer/Program.cs
+++ b/src/GraphDeployer/Program.cs
@@ -3,6 +3,7 @@ using Coscine.GraphDeployer.Logging;
 using Coscine.Metadata;
 using LibGit2Sharp;
 using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
 using NLog.Config;
 using NLog.Extensions.Logging;
 using System.Diagnostics;
@@ -41,6 +42,10 @@ public class Program
 
     private static void Run()
     {
+        var currentRun = new Dictionary<string, string>();
+        var lastRun = JsonConvert.DeserializeObject<Dictionary<string, string>>(Configuration.GetString("coscine/local/graph_deployer/last_run", "{}"));
+        lastRun ??= new Dictionary<string, string>();
+
         var virtuosoServer = Configuration.GetString("coscine/local/virtuoso/additional/url");
         var virtuosoHost = new Uri(virtuosoServer).Host;
         var virtuosoUser = Configuration.GetString("coscine/global/virtuoso_db_user");
@@ -111,6 +116,15 @@ public class Program
                 {
                     var graph = kv.Value.Item1;
                     var graphName = kv.Key.ToString();
+                    kv.Value.Item2.ForEach((path) => currentRun.TryAdd(graphName + path, HashUtil.GetFileHash(path)));
+                    var changed = kv.Value.Item2.Any((path) =>
+                        !lastRun.ContainsKey(graphName + path) || lastRun[graphName + path] != currentRun[graphName + path]);
+
+                    if (!changed)
+                    {
+                        _logger.LogInformation("Skipping {graphName}", graphName);
+                        continue;
+                    }
 
                     var currentGraph = Helpers.WrapRequest(() => _rdfStoreConnector.GetGraph(graphName));
 
@@ -121,27 +135,26 @@ public class Program
                     var graphWasChanged = graph.Triples.Count != currentGraph.Triples.Count
                                         || projectedGraph.Except(projectedCurrentGraph).Any();
 
-                    if (graphWasChanged)
+                    if (!graphWasChanged)
                     {
-                        if (!currentGraph.IsEmpty)
-                        {
-                            Helpers.WrapRequest(() => _rdfStoreConnector.ClearGraph(graphName));
-                            _logger.LogInformation("Cleared Graph {graphName}", graphName);
-                        }
-                        else
-                        {
-                            _logger.LogInformation("No Graph {graphName}", graphName);
-                        }
-
-                        foreach (var file in kv.Value.Item2)
-                        {
-                            var fileInfo = new FileInfo(file);
-                            queries.Add($"ld_dir('{fileInfo.DirectoryName[2..].Replace("\\", "/")}', '{fileInfo.Name}', '{graphName}');");
-                        }
+                        _logger.LogInformation("Skipping {graphName}", graphName);
+                        continue;
+                    }
+
+                    if (!currentGraph.IsEmpty)
+                    {
+                        Helpers.WrapRequest(() => _rdfStoreConnector.ClearGraph(graphName));
+                        _logger.LogInformation("Cleared Graph {graphName}", graphName);
                     }
                     else
                     {
-                        _logger.LogInformation("Skipping {graphName}", graphName);
+                        _logger.LogInformation("No Graph {graphName}", graphName);
+                    }
+
+                    foreach (var file in kv.Value.Item2)
+                    {
+                        var fileInfo = new FileInfo(file);
+                        queries.Add($"ld_dir('{fileInfo.DirectoryName[2..].Replace("\\", "/")}', '{fileInfo.Name}', '{graphName}');");
                     }
                 }
 
@@ -159,6 +172,7 @@ public class Program
             }
         }
 
+        Configuration.Put("coscine/local/graph_deployer/last_run", JsonConvert.SerializeObject(currentRun));
         _logger.LogInformation("Done");
     }
 
@@ -241,4 +255,4 @@ public class Program
                $"{triple.Predicate.ToString()}," +
                $"{(triple.Object.NodeType == NodeType.Blank ? "BLANK" : triple.Object.ToString())}";
     }
-}
\ No newline at end of file
+}