diff --git a/src/ServiceInsight.FunctionalTests/Services/FakeServiceControl.cs b/src/ServiceInsight.FunctionalTests/Services/FakeServiceControl.cs
index 32ab47267..725aa7ed7 100644
--- a/src/ServiceInsight.FunctionalTests/Services/FakeServiceControl.cs
+++ b/src/ServiceInsight.FunctionalTests/Services/FakeServiceControl.cs
@@ -33,11 +33,6 @@ public Uri CreateServiceInsightUri(StoredMessage message)
             return new Uri(string.Format("si://{0}/api{1}", Address, message.GetURIQuery()));
         }
 
-        public bool HasSagaChanged(Guid sagaId)
-        {
-            return true;
-        }
-
         public SagaData GetSagaById(Guid sagaId)
         {
             return new SagaData();
@@ -82,7 +77,7 @@ public IEnumerable<Endpoint> GetEndpoints()
             return Get<List<Endpoint>>("GetEndpoints");
         }
 
-        public IEnumerable<KeyValuePair<string, string>> GetMessageData(Guid messageId)
+        public IEnumerable<KeyValuePair<string, string>> GetMessageData(SagaMessage messageId)
         {
             return new List<KeyValuePair<string, string>>();
         }
diff --git a/src/ServiceInsight.sln.DotSettings b/src/ServiceInsight.sln.DotSettings
index 4664b5b2c..1f309a6b0 100644
--- a/src/ServiceInsight.sln.DotSettings
+++ b/src/ServiceInsight.sln.DotSettings
@@ -582,6 +582,7 @@ II.2.12 &lt;HandlesEvent /&gt;&#xD;
 	<s:String x:Key="/Default/CodeStyle/Naming/VBNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/VBNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpFileLayoutPatternsUpgrade/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
 	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002EJavaScript_002ECodeStyle_002ESettingsUpgrade_002EJsCodeFormatterSettingsUpgrader/@EntryIndexedValue">True</s:Boolean>
diff --git a/src/ServiceInsight/Saga/SagaMessage.cs b/src/ServiceInsight/Saga/SagaMessage.cs
index c48dad852..05b894709 100644
--- a/src/ServiceInsight/Saga/SagaMessage.cs
+++ b/src/ServiceInsight/Saga/SagaMessage.cs
@@ -92,9 +92,12 @@ public bool ShowData
 
         internal void RefreshData(IServiceControl serviceControl)
         {
-            if (Data != null) return;
+            if (Data != null)
+            {
+                return;
+            }
 
-            Data = serviceControl.GetMessageData(MessageId).Select(kvp => new SagaMessageDataItem { Key = kvp.Key, Value = kvp.Value }).ToList();
+            Data = serviceControl.GetMessageData(this).Select(kvp => new SagaMessageDataItem { Key = kvp.Key, Value = kvp.Value }).ToList();
         }
     }
 
diff --git a/src/ServiceInsight/Saga/SagaWindowViewModel.cs b/src/ServiceInsight/Saga/SagaWindowViewModel.cs
index b19fdc54c..ea51d158e 100644
--- a/src/ServiceInsight/Saga/SagaWindowViewModel.cs
+++ b/src/ServiceInsight/Saga/SagaWindowViewModel.cs
@@ -73,10 +73,10 @@ void RefreshMessageProperties(IEnumerable<SagaMessage> messages)
         public void Handle(SelectedMessageChanged @event)
         {
             var message = @event.Message;
-            RefreshSaga(message, a => true);
+            RefreshSaga(message);
         }
 
-        void RefreshSaga(StoredMessage message, Func<Guid, bool> HasChanged)
+        void RefreshSaga(StoredMessage message)
         {
             currentMessage = message;
             ShowSagaNotFoundWarning = false;
@@ -91,10 +91,7 @@ void RefreshSaga(StoredMessage message, Func<Guid, bool> HasChanged)
 
                 if (originatingSaga != null)
                 {
-                    if (HasChanged(originatingSaga.SagaId))
-                    {
-                        RefreshSaga(originatingSaga);
-                    }
+                    RefreshSaga(originatingSaga);
                 }
             }
         }
@@ -184,7 +181,7 @@ public void ShowFlow()
 
         public void RefreshSaga()
         {
-            RefreshSaga(currentMessage, serviceControl.HasSagaChanged);
+            RefreshSaga(currentMessage);
         }
 
         public SagaMessage SelectedMessage
diff --git a/src/ServiceInsight/ServiceControl/DefaultServiceControl.cs b/src/ServiceInsight/ServiceControl/DefaultServiceControl.cs
index 379ef49b3..39dbfc435 100644
--- a/src/ServiceInsight/ServiceControl/DefaultServiceControl.cs
+++ b/src/ServiceInsight/ServiceControl/DefaultServiceControl.cs
@@ -2,22 +2,24 @@
 {
     using System;
     using System.Collections.Generic;
+    using System.Collections.Specialized;
     using System.Linq;
     using System.Net;
+    using System.Runtime.Caching;
     using System.Xml;
     using System.Xml.Linq;
     using Anotar.Serilog;
     using Caliburn.Micro;
-    using Models;
     using Particular.ServiceInsight.Desktop.Framework.Events;
     using Particular.ServiceInsight.Desktop.Framework.MessageDecoders;
     using Particular.ServiceInsight.Desktop.Framework.Settings;
+    using Particular.ServiceInsight.Desktop.Models;
+    using Particular.ServiceInsight.Desktop.Saga;
+    using Particular.ServiceInsight.Desktop.Settings;
     using RestSharp;
     using RestSharp.Contrib;
     using RestSharp.Deserializers;
-    using Saga;
     using Serilog;
-    using Settings;
 
     public class DefaultServiceControl : IServiceControl
     {
@@ -32,6 +34,7 @@ public class DefaultServiceControl : IServiceControl
         private const string SagaEndpoint = "sagas/{0}";
 
         ServiceControlConnectionProvider connection;
+        MemoryCache cache;
         IEventAggregator eventAggregator;
         ProfilerSettings settings;
 
@@ -43,6 +46,7 @@ public DefaultServiceControl(
             this.connection = connection;
             this.eventAggregator = eventAggregator;
             settings = settingsProvider.GetSettings<ProfilerSettings>();
+            cache = new MemoryCache("ServiceControlReponses", new NameValueCollection(1) { { "cacheMemoryLimitMegabytes", settings.CacheSize.ToString() } });
         }
 
         public bool IsAlive()
@@ -52,15 +56,14 @@ public bool IsAlive()
 
         public string GetVersion()
         {
-            var request = new RestRequest();
+            var request = new RestRequestWithCache(RestRequestWithCache.CacheStyle.Immutable);
 
-            LogRequest(request);
-
-            var response = CreateClient().Execute(request);
-            var header = ProcessResponse(restResponse => restResponse.Headers.Single(x => x.Name == ServiceControlHeaders.ParticularVersion), response);
+            var header = Execute(request, restResponse => restResponse.Headers.Single(x => x.Name == ServiceControlHeaders.ParticularVersion));
 
             if (header == null)
+            {
                 return null;
+            }
 
             return header.Value.ToString();
         }
@@ -68,8 +71,8 @@ public string GetVersion()
         public void RetryMessage(string messageId)
         {
             var url = string.Format(RetryEndpoint, messageId);
-            var request = new RestRequest(url, Method.POST);
-            Execute(request, HasSucceeded);
+            var request = new RestRequestWithCache(url, Method.POST);
+            Execute(request, _ => true);
         }
 
         public Uri CreateServiceInsightUri(StoredMessage message)
@@ -78,14 +81,9 @@ public Uri CreateServiceInsightUri(StoredMessage message)
             return new Uri(string.Format("si://{0}:{1}/api{2}", connectionUri.Host, connectionUri.Port, message.GetURIQuery()));
         }
 
-        public bool HasSagaChanged(Guid sagaId)
-        {
-            return HasChanged(CreateSagaRequest(sagaId));
-        }
-
         public SagaData GetSagaById(Guid sagaId)
         {
-            return GetModel<SagaData>(CreateSagaRequest(sagaId)) ?? new SagaData();
+            return GetModel<SagaData>(new RestRequestWithCache(string.Format(SagaEndpoint, sagaId), RestRequestWithCache.CacheStyle.IfNotModified)) ?? new SagaData();
         }
 
         public PagedResult<StoredMessage> Search(string searchQuery, int pageIndex = 1, string orderBy = null, bool ascending = false)
@@ -120,7 +118,7 @@ public PagedResult<StoredMessage> GetAuditMessages(Endpoint endpoint, string sea
 
         public IEnumerable<StoredMessage> GetConversationById(string conversationId)
         {
-            var request = new RestRequest(string.Format(ConversationEndpoint, conversationId));
+            var request = new RestRequestWithCache(String.Format(ConversationEndpoint, conversationId), RestRequestWithCache.CacheStyle.IfNotModified);
             var messages = GetModel<List<StoredMessage>>(request) ?? new List<StoredMessage>();
 
             return messages;
@@ -128,30 +126,38 @@ public IEnumerable<StoredMessage> GetConversationById(string conversationId)
 
         public IEnumerable<Endpoint> GetEndpoints()
         {
-            var request = new RestRequest(EndpointsEndpoint);
+            var request = new RestRequestWithCache(EndpointsEndpoint, RestRequestWithCache.CacheStyle.IfNotModified);
             var messages = GetModel<List<Endpoint>>(request);
 
             return messages ?? new List<Endpoint>();
         }
 
-        public IEnumerable<KeyValuePair<string, string>> GetMessageData(Guid messageId)
+        public IEnumerable<KeyValuePair<string, string>> GetMessageData(SagaMessage message)
         {
-            var request = new RestRequest(String.Format(MessageBodyEndpoint, messageId));
+            var request = new RestRequestWithCache(String.Format(MessageBodyEndpoint, message.MessageId), message.Status == MessageStatus.Successful ? RestRequestWithCache.CacheStyle.Immutable : RestRequestWithCache.CacheStyle.IfNotModified);
+
+            var body = Execute(request, response => response.Content);
+
+            if (body == null)
+            {
+                return Enumerable.Empty<KeyValuePair<string, string>>();
+            }
 
-            return Execute(request, response =>
-                response.Content.StartsWith("<?xml") ?
-                    GetXmlData(response.Content) :
-                    JsonPropertiesHelper.ProcessValues(response.Content, CleanupBodyString))
-                ?? Enumerable.Empty<KeyValuePair<string, string>>();
+            return body.StartsWith("<?xml") ?
+                GetXmlData(body) :
+                JsonPropertiesHelper.ProcessValues(body, CleanupBodyString);
         }
 
         public void LoadBody(StoredMessage message)
         {
-            var client = message.BodyUrl.StartsWith("http") ? CreateClient(message.BodyUrl) : CreateClient();
-
-            var request = new RestRequest(message.BodyUrl, Method.GET);
+            var request = new RestRequestWithCache(message.BodyUrl, message.Status == MessageStatus.Successful ? RestRequestWithCache.CacheStyle.Immutable : RestRequestWithCache.CacheStyle.IfNotModified);
 
-            message.Body = Execute(client, request, response => response.Content);
+            var baseUrl = message.BodyUrl;
+            if (!baseUrl.StartsWith("http"))
+            {
+                baseUrl = null; // We use the default
+            }
+            message.Body = Execute(request, response => response.Content, baseUrl);
         }
 
         void AppendSystemMessages(IRestRequest request)
@@ -177,14 +183,9 @@ void AppendSearchQuery(IRestRequest request, string searchQuery)
             request.Resource += string.Format("search/{0}", HttpUtility.UrlEncode(searchQuery));
         }
 
-        IRestClient CreateClient()
-        {
-            return CreateClient(connection.Url);
-        }
-
-        IRestClient CreateClient(string url)
+        IRestClient CreateClient(string baseUrl = null)
         {
-            var client = new RestClient(url);
+            var client = new RestClient(baseUrl ?? connection.Url);
             var deserializer = new JsonMessageDeserializer();
             var xdeserializer = new XmlDeserializer();
             client.ClearHandlers();
@@ -202,96 +203,191 @@ IRestClient CreateClient(string url)
             return client;
         }
 
-        static RestRequest CreateSagaRequest(Guid sagaId)
+        static RestRequestWithCache CreateMessagesRequest(string endpointName = null)
         {
-            return new RestRequest(string.Format(SagaEndpoint, sagaId));
+            return endpointName != null
+                ? new RestRequestWithCache(String.Format(EndpointMessagesEndpoint, endpointName), RestRequestWithCache.CacheStyle.IfNotModified)
+                : new RestRequestWithCache(MessagesEndpoint, RestRequestWithCache.CacheStyle.IfNotModified);
         }
 
-        static RestRequest CreateMessagesRequest(string endpointName = null)
+        PagedResult<T> GetPagedResult<T>(RestRequestWithCache request) where T : class, new()
         {
-            return endpointName != null ? new RestRequest(string.Format(EndpointMessagesEndpoint, endpointName)) : new RestRequest(MessagesEndpoint);
+            var result = Execute<PagedResult<T>, List<T>>(request, response => new PagedResult<T>
+                {
+                    Result = response.Data,
+                    TotalCount = int.Parse(response.Headers.First(x => x.Name == ServiceControlHeaders.TotalCount).Value.ToString())
+                });
+
+            return result;
         }
 
-        bool HasChanged(IRestRequest request)
+        T GetModel<T>(RestRequestWithCache request)
+            where T : class, new()
         {
-            if (System.Runtime.Caching.MemoryCache.Default.Any(c => c.Key == request.Resource))
+            return Execute<T, T>(request, response => response.Data);
+        }
+
+        T Execute<T>(RestRequestWithCache request, Func<IRestResponse, T> selector, string baseUrl = null)
+        {
+            var cacheStyle = request.CacheSyle;
+            var restClient = CreateClient(baseUrl);
+
+            switch (cacheStyle)
             {
-                var method = request.Method;
-                try
-                {
-                    request.Method = Method.HEAD;
-                    var response = CreateClient().Execute(request);
+                case RestRequestWithCache.CacheStyle.None:
+                    break;
+                case RestRequestWithCache.CacheStyle.Immutable:
+                    var item = cache.Get(CacheKey(restClient, request));
 
-                    var etag = response.Headers.FirstOrDefault(h => h.Name == "ETag");
-                    if (etag == null) return true;
-                    return !System.Runtime.Caching.MemoryCache.Default.Any(c => c.Key == request.Resource &&
-                        string.Equals(((RestSharp.Parameter)c.Value).Value, etag.Value));
-                }
-                finally
-                {
-                    request.Method = method;
-                }
-            }
+                    if (item != null)
+                    {
+                        return (T) item;
+                    }
 
-            return true;
-        }
+                    break;
+                case RestRequestWithCache.CacheStyle.IfNotModified:
+                    var obj = cache.Get(CacheKey(restClient, request));
+
+                    if (obj != null)
+                    {
+                        var tuple = (Tuple<string, T>) obj;
+                        request.AddHeader("If-None-Match", tuple.Item1);
+                    }
+
+                    break;
+            }
 
-        PagedResult<T> GetPagedResult<T>(IRestRequest request) where T : class, new()
-        {
             LogRequest(request);
 
-            var response = CreateClient().Execute<List<T>>(request);
+            var response = restClient.Execute(request);
 
-            if (HasSucceeded(response))
-            {
-                LogResponse(response);
-                return new PagedResult<T>
-                {
-                    Result = response.Data,
-                    TotalCount = int.Parse(response.Headers.First(x => x.Name == ServiceControlHeaders.TotalCount).Value.ToString())
-                };
-            }
-            else
+            var data = default(T);
+
+            switch (cacheStyle)
             {
-                LogError(response);
-                return new PagedResult<T>();
+                case RestRequestWithCache.CacheStyle.Immutable:
+                    if (response.StatusCode == HttpStatusCode.OK)
+                    {
+                        data = ProcessResponse(selector, response);
+                        cache.Set(CacheKey(restClient, request), data, new CacheItemPolicy());
+                    }
+                    break;
+
+                case RestRequestWithCache.CacheStyle.IfNotModified:
+                    switch (response.StatusCode)
+                    {
+                        case HttpStatusCode.OK:
+                            data = ProcessResponse(selector, response);
+                            var etag = response.Headers.FirstOrDefault(h => h.Name == "ETag");
+                            if (etag != null)
+                            {
+                                cache.Set(CacheKey(restClient, request), Tuple.Create(etag, data), new CacheItemPolicy());
+                            }
+                            break;
+                        case HttpStatusCode.NotModified:
+                            LogResponse(response);
+
+                            var obj = cache.Get(CacheKey(restClient, request));
+
+                            if (obj != null)
+                            {
+                                var tuple = (Tuple<string, T>) obj;
+                                data = tuple.Item2;
+                            }
+                            break;
+                    }
+                    break;
+                default:
+                    data = ProcessResponse(selector, response);
+                    break;
             }
+
+            return data;
         }
 
-        T GetModel<T>(IRestRequest request)
+        T Execute<T, T2>(RestRequestWithCache request, Func<IRestResponse<T2>, T> selector)
             where T : class, new()
+            where T2 : class, new()
         {
-            return Execute<T>(request, response => { CacheResponse(response); return response.Data; });
-        }
+            var cacheStyle = request.CacheSyle;
+            var restClient = CreateClient();
 
-        T Execute<T>(IRestRequest request, Func<IRestResponse, T> selector)
-        {
-            return Execute(CreateClient(), request, selector);
-        }
+            switch (cacheStyle)
+            {
+                case RestRequestWithCache.CacheStyle.None:
+                    break;
+                case RestRequestWithCache.CacheStyle.Immutable:
+                    var item = cache.Get(CacheKey(restClient, request));
 
-        T Execute<T>(IRestClient client, IRestRequest request, Func<IRestResponse, T> selector)
-        {
-            LogRequest(request);
+                    if (item != null)
+                    {
+                        return (T)item;
+                    }
 
-            var response = client.Execute(request);
-            return ProcessResponse(selector, response);
-        }
+                    break;
+                case RestRequestWithCache.CacheStyle.IfNotModified:
+                    var obj = cache.Get(CacheKey(restClient, request));
+
+                    if (obj != null)
+                    {
+                        var tuple = (Tuple<string, T>)obj;
+                        request.AddHeader("If-None-Match", tuple.Item1);
+                    }
+
+                    break;
+            }
 
-        T Execute<T>(IRestRequest request, Func<IRestResponse<T>, T> selector)
-            where T : class, new()
-        {
             LogRequest(request);
 
-            var response = CreateClient().Execute<T>(request);
-            return ProcessResponse(selector, response);
-        }
+            var response = restClient.Execute<T2>(request);
 
-        static void CacheResponse(IRestResponse response)
-        {
-            if (response.Request.Resource != null && response.Headers.Any(h => h.Name == "ETag"))
+            var data = default(T);
+
+            switch (cacheStyle)
             {
-                System.Runtime.Caching.MemoryCache.Default.Add(new System.Runtime.Caching.CacheItem(response.Request.Resource, response.Headers.FirstOrDefault(h => h.Name == "ETag")), new System.Runtime.Caching.CacheItemPolicy());
+                case RestRequestWithCache.CacheStyle.Immutable:
+                    if (response.StatusCode == HttpStatusCode.OK)
+                    {
+                        data = ProcessResponse(selector, response);
+                        cache.Set(CacheKey(restClient, request), data, new CacheItemPolicy());
+                    }
+                    break;
+
+                case RestRequestWithCache.CacheStyle.IfNotModified:
+                    switch (response.StatusCode)
+                    {
+                        case HttpStatusCode.OK:
+                            data = ProcessResponse(selector, response);
+                            var etag = response.Headers.FirstOrDefault(h => h.Name == "ETag");
+                            if (etag != null)
+                            {
+                                cache.Set(CacheKey(restClient, request), Tuple.Create(etag.Value.ToString(), data), new CacheItemPolicy());
+                            }
+                            break;
+                        case HttpStatusCode.NotModified:
+                            LogResponse(response);
+
+                            var obj = cache.Get(CacheKey(restClient, request));
+
+                            if (obj != null)
+                            {
+                                var tuple = (Tuple<string, T>)obj;
+                                data = tuple.Item2;
+                            }
+                            break;
+                    }
+                    break;
+                default:
+                    data = ProcessResponse(selector, response);
+                    break;
             }
+
+            return data;
+        }
+
+        static string CacheKey(IRestClient restClient, IRestRequest request)
+        {
+            return restClient.BuildUri(request).AbsoluteUri;
         }
 
         T ProcessResponse<T>(Func<IRestResponse, T> selector, IRestResponse response)
@@ -301,25 +397,21 @@ T ProcessResponse<T>(Func<IRestResponse, T> selector, IRestResponse response)
                 LogResponse(response);
                 return selector(response);
             }
-            else
-            {
-                LogError(response);
-                return default(T);
-            }
+
+            LogError(response);
+            return default(T);
         }
 
-        T ProcessResponse<T>(Func<IRestResponse<T>, T> selector, IRestResponse<T> response)
+        T ProcessResponse<T, T2>(Func<IRestResponse<T2>, T> selector, IRestResponse<T2> response)
         {
             if (HasSucceeded(response))
             {
                 LogResponse(response);
                 return selector(response);
             }
-            else
-            {
-                LogError(response);
-                return default(T);
-            }
+
+            LogError(response);
+            return default(T);
         }
 
         IEnumerable<KeyValuePair<string, string>> GetXmlData(string bodyString)
@@ -351,12 +443,12 @@ static string CleanupBodyString(string bodyString)
             return bodyString.Replace("\u005c", string.Empty).Replace("\uFEFF", string.Empty).TrimStart("[\"".ToCharArray()).TrimEnd("]\"".ToCharArray());
         }
 
-        void LogRequest(IRestRequest request)
+        void LogRequest(RestRequestWithCache request)
         {
             var resource = request.Resource != null ? request.Resource.TrimStart('/') : string.Empty;
             var url = connection.Url != null ? connection.Url.TrimEnd('/') : string.Empty;
 
-            LogTo.Information("HTTP {Method} {url:l}/{resource:l}", request.Method, url, resource);
+            LogTo.Information("HTTP {Method} {url:l}/{resource:l} ({CacheSyle})", request.Method, url, resource, request.CacheSyle);
 
             foreach (var parameter in request.Parameters)
             {
@@ -395,6 +487,6 @@ static bool HasSucceeded(IRestResponse response)
             return SuccessCodes.Any(x => response != null && x == response.StatusCode && response.ErrorException == null);
         }
 
-        static IEnumerable<HttpStatusCode> SuccessCodes = new[] { HttpStatusCode.OK, HttpStatusCode.Accepted };
+        static IEnumerable<HttpStatusCode> SuccessCodes = new[] { HttpStatusCode.OK, HttpStatusCode.Accepted, HttpStatusCode.NotModified };
     }
 }
\ No newline at end of file
diff --git a/src/ServiceInsight/ServiceControl/IServiceControl.cs b/src/ServiceInsight/ServiceControl/IServiceControl.cs
index 29aaf5d0f..ad57f6ba0 100644
--- a/src/ServiceInsight/ServiceControl/IServiceControl.cs
+++ b/src/ServiceInsight/ServiceControl/IServiceControl.cs
@@ -15,8 +15,6 @@ public interface IServiceControl
 
         Uri CreateServiceInsightUri(StoredMessage message);
 
-        bool HasSagaChanged(Guid sagaId);
-
         SagaData GetSagaById(Guid sagaId);
 
         PagedResult<StoredMessage> Search(string searchQuery, int pageIndex = 1, string orderBy = null, bool ascending = false);
@@ -27,7 +25,7 @@ public interface IServiceControl
 
         IEnumerable<Endpoint> GetEndpoints();
 
-        IEnumerable<KeyValuePair<string, string>> GetMessageData(Guid messageId);
+        IEnumerable<KeyValuePair<string, string>> GetMessageData(SagaMessage messageId);
 
         void LoadBody(StoredMessage message);
     }
diff --git a/src/ServiceInsight/ServiceControl/RestRequestWithCache.cs b/src/ServiceInsight/ServiceControl/RestRequestWithCache.cs
new file mode 100644
index 000000000..3f4cfb03d
--- /dev/null
+++ b/src/ServiceInsight/ServiceControl/RestRequestWithCache.cs
@@ -0,0 +1,32 @@
+namespace Particular.ServiceInsight.Desktop.ServiceControl
+{
+    using RestSharp;
+
+    public class RestRequestWithCache : RestRequest
+    {
+        public RestRequestWithCache(CacheStyle cacheStyle)
+        {
+            CacheSyle = cacheStyle;
+        }
+
+        public RestRequestWithCache(string resource, CacheStyle cacheStyle)
+            : this(resource, Method.GET, cacheStyle)
+        {
+        }
+
+        public RestRequestWithCache(string resource, Method method, CacheStyle cacheStyle = CacheStyle.None)
+            : base(resource, method)
+        {
+            CacheSyle = cacheStyle;
+        }
+
+        public CacheStyle CacheSyle { get; set; }
+
+        public enum CacheStyle
+        {
+            None,
+            Immutable,
+            IfNotModified
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/ServiceInsight/ServiceInsight.csproj b/src/ServiceInsight/ServiceInsight.csproj
index b52e8be4b..00871e4a5 100644
--- a/src/ServiceInsight/ServiceInsight.csproj
+++ b/src/ServiceInsight/ServiceInsight.csproj
@@ -250,6 +250,7 @@
     <Compile Include="ExtensionMethods\ViewModelExtensions.cs" />
     <Compile Include="LogWindow\LogMessage.cs" />
     <Compile Include="SequenceDiagram\MessageLineConverter.cs" />
+    <Compile Include="ServiceControl\RestRequestWithCache.cs" />
     <Compile Include="ValueConverters\BoolToStrokeDashArrayConverter.cs" />
     <Compile Include="SequenceDiagram\EndpointInfo.cs" />
     <Compile Include="SequenceDiagram\EndpointPositionConverter.cs" />
diff --git a/src/ServiceInsight/Settings/ProfilerSettings.cs b/src/ServiceInsight/Settings/ProfilerSettings.cs
index 80149c1eb..337f66b65 100644
--- a/src/ServiceInsight/Settings/ProfilerSettings.cs
+++ b/src/ServiceInsight/Settings/ProfilerSettings.cs
@@ -8,7 +8,7 @@
     // Properties without a DisplayNameAttribute aren't automatically added to the options dialog.
     public class ProfilerSettings : PropertyChangedBase
     {
-        int autoRefresh;
+        int autoRefresh, cacheSize;
 
         public ProfilerSettings()
         {
@@ -16,6 +16,15 @@ public ProfilerSettings()
             RecentServiceControlEntries = new ObservableCollection<string>();
         }
 
+        [DefaultValue(20)]
+        [DisplayName("In-Memory Cache Size")]
+        [Description("Sets the maximum size to use for caching data in-memory in MB")]
+        public int CacheSize
+        {
+            get { return Math.Max(5, cacheSize); }
+            set { cacheSize = value; }
+        }
+
         [DefaultValue(15)]
         [DisplayName("AutoRefresh Timer")]
         [Description("Auto refresh time in seconds")]