diff --git a/beat/web/reports/static/reports/app/directives/downloadLink.js b/beat/web/reports/static/reports/app/directives/downloadLink.js
index 3b16d0dac7b7a582aaddf647a62620759b144210..4510f1d3ba1158589f9f3a992dc509f839b4d3f8 100644
--- a/beat/web/reports/static/reports/app/directives/downloadLink.js
+++ b/beat/web/reports/static/reports/app/directives/downloadLink.js
@@ -66,7 +66,7 @@ angular.module('reportApp')
         <span class="caret"></span>
     </button>
     <ul class="dropdown-menu">
-        <li><a ng-repeat='t in filetypes' ng-click='downloadImgs($event, t)'>{{ t }}</a></li>
+        <li><a ng-repeat='t in filetypes track by t' ng-click='downloadImgs($event, t)'>{{ t }}</a></li>
     </ul>
 </div>
 <a id='{{ domId }}-download'></a>
diff --git a/beat/web/reports/static/reports/app/directives/edit/addItemsMenu.js b/beat/web/reports/static/reports/app/directives/edit/addItemsMenu.js
index d9ea7e3e6af9b039ca47d3072ab7ef0739837e0f..85e26e675bf33bb3f269795a1863d34d645c8b2e 100644
--- a/beat/web/reports/static/reports/app/directives/edit/addItemsMenu.js
+++ b/beat/web/reports/static/reports/app/directives/edit/addItemsMenu.js
@@ -124,8 +124,8 @@ angular.module('reportApp')
         Add Plot
         <span class="caret"></span>
     </button>
-    <ul class='dropdown-menu' ng-repeat='(expName, plots) in plottables' ng-if='expName === group.experiments[0]'>
-        <li ng-repeat='plot in plots'>
+    <ul class='dropdown-menu' ng-repeat='(expName, plots) in plottables track by expName' ng-if='expName === group.experiments[0]'>
+        <li ng-repeat='plot in plots track by plot.label'>
             <a ng-click='addNewPlot(plot)'>{{ plot.label }} <i>({{ plot.type }})</i></a>
         </li>
     </ul>
diff --git a/beat/web/reports/static/reports/app/directives/edit/tableFieldSelector.js b/beat/web/reports/static/reports/app/directives/edit/tableFieldSelector.js
index e621ce683958626e92c4544d9e46b7dad454a93f..89a0776295bb8318eac3f3b02160df6694884959 100644
--- a/beat/web/reports/static/reports/app/directives/edit/tableFieldSelector.js
+++ b/beat/web/reports/static/reports/app/directives/edit/tableFieldSelector.js
@@ -49,9 +49,13 @@ angular.module('reportApp')
                 scope.buttonAction()();
             };
 
+            scope.tableablesCache = {};
             scope.tableables = () => {
                 // start with the tableables generated in experimentsservice
                 const tableables = ExperimentsService.tableables;
+		const cacheKey = Object.keys(tableables).length;
+		if(scope.tableablesCache[cacheKey])
+		    return scope.tableablesCache[cacheKey];
                 const fieldArr = Object.entries(tableables)
                 // only look at fields that are from an experiment in the group
                 .filter(([e, fields]) => scope.group.experiments.includes(e))
@@ -65,9 +69,13 @@ angular.module('reportApp')
                 // removing dups
                 const arr = Array.from(new Set(fieldArr));
 
+		scope.tableablesCache[cacheKey] = arr;
                 return arr;
             };
 
+            /* This always returns true, because it's only called with 1 arg which is basically [expName, fieldName].join('.')
+	     * Due to the removing dups step in scope.tableables(), I dont think this is necessary, but keep this here if it turns out to be!
+	     * This func checks if the field name has already been given a spot in the available columns list.
             // has this fieldName already been processed?
             // need to look at the already-processed field names
             scope.isUniqueTableable = (expName, fieldName) => {
@@ -94,6 +102,7 @@ angular.module('reportApp')
                 // if it isnt a repeat, its unique!
                 return !isRepeat;
             };
+            */
 
             // many tableable fields are fields from an analyzer, a block, or something else
             // these fields have a field group name, a '.', and an actual field name
@@ -116,10 +125,9 @@ angular.module('reportApp')
             scope.subfieldName = (field) => field.includes('.') ? field.split('.').slice(1).join('.') : field;
 
             scope.shouldShowField = (fName, gName) => {
-                const isUnique = scope.isUniqueTableable(fName);
                 const isInGroup = scope.groupName(fName) == gName;
 
-                return isUnique && isInGroup;
+                return isInGroup;
             }
 
             // toggle the selection of a field
@@ -144,8 +152,8 @@ angular.module('reportApp')
         <fieldset>
             <h4>General</h4>
             <div
-                ng-repeat='fName in tableables()'
-                ng-if="isUniqueTableable(fName) && !fName.includes('.')">
+                ng-repeat='fName in tableables() track by fName'
+                ng-if="!fName.includes('.')">
                 <label>
                     <input
                         type='checkbox'
@@ -156,10 +164,10 @@ angular.module('reportApp')
                 </label>
             </div>
         </fieldset>
-        <fieldset ng-repeat='gName in tableablesGroups()'>
+        <fieldset ng-repeat='gName in tableablesGroups() track by gName'>
             <h4>{{ gName }}</h4>
             <div
-                ng-repeat='fName in tableables()'
+                ng-repeat='fName in tableables() track by fName'
                 ng-if='shouldShowField(fName, gName)'>
                 <label>
                     <input
@@ -173,19 +181,19 @@ angular.module('reportApp')
         </fieldset>
     </form>
     <!--
-    <select multiple ng-model='colsSelected'>
+    <select multiple ng-model='colsSelected' ng-model-options="{ debounce: 100 }">
         <optgroup label='General'>
             <option
-                ng-repeat='fName in tableables()'
-                ng-if="isUniqueTableable(fName) && !fName.includes('.')"
+                ng-repeat='fName in tableables() track by fName'
+                ng-if="!fName.includes('.')"
                 value='{{ fName }}'>
                 {{ fName }}
             </option>
         </optgroup>
-        <optgroup ng-repeat='gName in tableablesGroups()' label='{{ gName }}'>
+        <optgroup ng-repeat='gName in tableablesGroups() track by gName' label='{{ gName }}'>
             <option
-                ng-repeat='fName in tableables()'
-                ng-if='isUniqueTableable(fName) && fName.startsWith(gName)'
+                ng-repeat='fName in tableables() track by fName'
+                ng-if='fName.startsWith(gName)'
                 value='{{ fName }}'>
                 {{ subfieldName(fName) }}
             </option>
diff --git a/beat/web/reports/static/reports/app/directives/editableLabel.js b/beat/web/reports/static/reports/app/directives/editableLabel.js
index dbc5b9ccd01fb50eed671533acc9eb29760a4a97..82f7a2f6400c65e5fabd923e68ed4e0e217c0196 100644
--- a/beat/web/reports/static/reports/app/directives/editableLabel.js
+++ b/beat/web/reports/static/reports/app/directives/editableLabel.js
@@ -44,7 +44,9 @@ angular.module('reportApp').directive("editableLabel", ['UrlService', function(U
         type='text'
         class='form-control'
         placeholder='A label...'
-        ng-model='obj[field]'/>
+        ng-model='obj[field]'
+        ng-model-options="{ debounce: 500 }"
+	/>
 </span>
 `
     };
diff --git a/beat/web/reports/static/reports/app/directives/experimentsTable.js b/beat/web/reports/static/reports/app/directives/experimentsTable.js
index 9b96493927af12f866efc432564e2daadea13625..ae111e80d05e0b7bcd4b12abda05f2c7f1bb7d7a 100644
--- a/beat/web/reports/static/reports/app/directives/experimentsTable.js
+++ b/beat/web/reports/static/reports/app/directives/experimentsTable.js
@@ -93,7 +93,7 @@ angular.module('reportApp')
                     </tr>
                 </thead>
                 <tbody>
-                    <tr ng-repeat='expName in expNames'>
+                    <tr ng-repeat='expName in expNames track by expName'>
                         <td ng-if='!isViewmode()'>
                             <div class='btn-group action-buttons'>
                                 <span
@@ -114,7 +114,7 @@ angular.module('reportApp')
                         </td>
                         <td><a href='{{ getExpUrl(expName) }}'>{{ expName }}</a></td>
                         <td>
-                            <span ng-repeat='db in getExpDatabases(expName)'>
+                            <span ng-repeat='db in getExpDatabases(expName) track by db'>
                                 <a href='{{ getDatabaseUrl(db.split("@")[0]) }}'>{{ db }}</a>
                                 &nbsp;
                             </span>
diff --git a/beat/web/reports/static/reports/app/directives/layout.js b/beat/web/reports/static/reports/app/directives/layout.js
index 27ae4d1896269620ee4490e95caa78e27e59a9fc..7da4fe37eeb45c9f6be806bbad71e9c96cbca254 100644
--- a/beat/web/reports/static/reports/app/directives/layout.js
+++ b/beat/web/reports/static/reports/app/directives/layout.js
@@ -48,6 +48,7 @@ angular.module('reportApp').directive("groupsLayout", ['GroupsService', 'UrlServ
     <div ng-if='!isViewmode() || GroupsService.groups.length > 1'
         ui-sortable='sortableOptions'
         ng-model='GroupsService.groups'
+        ng-model-options="{ debounce: 500 }"
         id='groupsLayout'
         class='panel-group'>
         <div
diff --git a/beat/web/reports/static/reports/app/directives/panelExperiments.js b/beat/web/reports/static/reports/app/directives/panelExperiments.js
index 5ed6d3e2dfdbf9bb207dcfecfa3c3bef53003a5e..c831da8272ad0bfa0cbf3e34752e01d3f2b690a7 100644
--- a/beat/web/reports/static/reports/app/directives/panelExperiments.js
+++ b/beat/web/reports/static/reports/app/directives/panelExperiments.js
@@ -96,7 +96,7 @@ angular.module('reportApp').directive("groupPanelExperiments", ['GroupsService',
                 </button>
                 <ul class="dropdown-menu" aria-labelledby="{{ dropdownId }}">
                     <li
-                        ng-repeat='exp in expsNotInGroup()'
+                        ng-repeat='exp in expsNotInGroup() track by exp'
                         ng-click='group.addExperiment(exp, getAnalyzerFromExpName(exp))'>
                         <a>{{ exp }}</a>
                     </li>
@@ -135,7 +135,7 @@ angular.module('reportApp').directive("groupPanelExperiments", ['GroupsService',
                             </span>
                         </div>
                     </td>
-                    <td ng-if='!isViewmode()'><input ng-model='group.aliases[expName]'></input></td>
+                    <td ng-if='!isViewmode()'><input ng-model='group.aliases[expName]' ng-model-options="{ debounce: 500 }"></input></td>
                     <td ng-if='isViewmode()'><span>{{ group.aliases[expName] }}</span></td>
                     <td><a href='{{ getExpUrl(expName) }}'>{{ getExpName(expName) }}</a></td>
                     <td>
diff --git a/beat/web/reports/static/reports/app/directives/panelItems.js b/beat/web/reports/static/reports/app/directives/panelItems.js
index 28df1fdd08b30633950e01e978f69deae9e06fcc..c9184b515fd20098c4c5780b7fa4ece8d02df331 100644
--- a/beat/web/reports/static/reports/app/directives/panelItems.js
+++ b/beat/web/reports/static/reports/app/directives/panelItems.js
@@ -40,8 +40,8 @@ angular.module('reportApp').directive("groupPanelItems", [function(){
             };
         },
         template: `
-<div ui-sortable='sortableOptions' ng-model='group._reportItems' class='panel-group'>
-    <div ng-repeat='item in group.reportItems'>
+<div ui-sortable='sortableOptions' ng-model='group._reportItems' ng-model-options="{ debounce: 500 }" class='panel-group'>
+    <div ng-repeat='item in group.reportItems track by $index'>
         <div group-table-item
             style='margin-bottom: 5px;'
             ng-if="item.id.includes('table')"
diff --git a/beat/web/reports/static/reports/app/directives/plotItem.js b/beat/web/reports/static/reports/app/directives/plotItem.js
index 6fa23841354c290bb22246bc0424b153a65a1933..209055bdfcf5993ef21bc8765b0af67f9cb754dc 100644
--- a/beat/web/reports/static/reports/app/directives/plotItem.js
+++ b/beat/web/reports/static/reports/app/directives/plotItem.js
@@ -125,7 +125,7 @@ angular.module('reportApp')
                     <span class="caret"></span>
                 </button>
                 <ul class="dropdown-menu">
-                    <li ng-click='content.savedPlotter = p' ng-repeat='p in getPossiblePlotters()'><a>{{ p }}</a></li>
+                    <li ng-click='content.savedPlotter = p' ng-repeat='p in getPossiblePlotters() track by p'><a>{{ p }}</a></li>
                 </ul>
             </div>
             <div class='btn-group' role='group'>
@@ -140,7 +140,7 @@ angular.module('reportApp')
                     <span class="caret"></span>
                 </button>
                 <ul class="dropdown-menu">
-                    <li ng-click='content.savedConfig = c' ng-repeat='c in getPossibleConfigs()'><a>{{ c }}</a></li>
+                    <li ng-click='content.savedConfig = c' ng-repeat='c in getPossibleConfigs() track by c'><a>{{ c }}</a></li>
                 </ul>
             </div>
         </div>
diff --git a/beat/web/reports/static/reports/app/directives/publish.js b/beat/web/reports/static/reports/app/directives/publish.js
index fe68cb35a868895f47e0fc6bef8b3adf1d037ac1..a886f3806597df5678603ede4acf2f6a24b72fb4 100644
--- a/beat/web/reports/static/reports/app/directives/publish.js
+++ b/beat/web/reports/static/reports/app/directives/publish.js
@@ -100,7 +100,7 @@ angular.module('reportApp')
                     </tr>
                 </thead>
                 <tbody>
-                    <tr ng-repeat='alg in algorithms'>
+                    <tr ng-repeat='alg in algorithms track by alg'>
                         <td><input type='radio' name='{{ alg }}' ng-model='radios[alg]' value='visible'></td>
                         <td><input type='radio' name='{{ alg }}' ng-model='radios[alg]' value='openSource' checked></td>
                         <td>{{ alg }}</td>
diff --git a/beat/web/reports/static/reports/app/directives/tableItem.js b/beat/web/reports/static/reports/app/directives/tableItem.js
index 036c1678d5727ca3cb4f2db75aa8fba4eb9d3834..f70b1f45570c8abc71944847bf8a5c58305a78d2 100644
--- a/beat/web/reports/static/reports/app/directives/tableItem.js
+++ b/beat/web/reports/static/reports/app/directives/tableItem.js
@@ -86,16 +86,21 @@ angular.module('reportApp')
             // get possible table entries
             scope.tableables = ExperimentsService.tableables || {};
 
+            scope.fieldTypeCache = {};
             // gets the field type (int, float, string, nothing)
             scope.getFieldType = (field) => {
+                if(scope.fieldTypeCache[field])
+		    return scope.fieldTypeCache[field];
+
+                let type;
                 if(field === scope.fields[0]){
-                    return 'string';
+                    type = 'string';
+                    scope.fieldTypeCache[field] = type;
                 }
 
                 let hasFieldObj = Object.values(scope.tableables)
                 .find(o => o[field]);
                 let fVal = hasFieldObj ? hasFieldObj[field] : {};
-                let type;
                 if(fVal.type){
                     type = fVal.type;
                 } else if(Number.isSafeInteger(fVal)){
@@ -108,6 +113,7 @@ angular.module('reportApp')
                     type = undefined;
                 }
 
+                scope.fieldTypeCache[field] = type;
                 return type;
             };
             // gets the field val for the given exp
@@ -238,7 +244,7 @@ angular.module('reportApp')
                     <span class="caret"></span>
                 </button>
                 <ul class="dropdown-menu" aria-labelledby="{{domId}}-precision">
-                    <li ng-click='content.precision = i' ng-repeat='i in floatingPointRange'><a>{{ i }}</a></li>
+                    <li ng-click='content.precision = i' ng-repeat='i in floatingPointRange track by i'><a>{{ i }}</a></li>
                 </ul>
             </div>
             <button class='btn btn-default' ng-click='toggleViewingCSV()'>
@@ -254,7 +260,7 @@ angular.module('reportApp')
             <div ng-if='!isViewingCSV.val' style='height: 100%; overflow-x: auto;'>
                 <table class="table table-striped table-hover">
                     <thead>
-                        <tr ui-sortable='sortableOptions' ng-model='fields'>
+                        <tr ui-sortable='sortableOptions' ng-model='fields' ng-model-options="{ debounce: 500 }">
                             <th ng-repeat='field in fields'>
                                 <span
                                     ng-if="sortField.val == field"
diff --git a/beat/web/reports/static/reports/app/services/plotService.js b/beat/web/reports/static/reports/app/services/plotService.js
index b3efb372abb29fd1b5e3aa1ea404136880d43c26..bfb4c62bd8a9b7d785d906273be1f6ac4f48a844 100644
--- a/beat/web/reports/static/reports/app/services/plotService.js
+++ b/beat/web/reports/static/reports/app/services/plotService.js
@@ -31,6 +31,7 @@
  *  - Rendering
  */
 angular.module('reportApp').factory('PlotService', ['UrlService', function(UrlService){
+    console.log('in PlotService');
     const ps = {
         // these are provided by ReportService
         plotters: [],
diff --git a/beat/web/reports/static/reports/app/services/reportService.js b/beat/web/reports/static/reports/app/services/reportService.js
index ff9a97f588ee5c9fe4bb9a76d7cf0758c39ee578..4d047c88bf4a7fa70e2ce15a1b5d7185efd632e4 100644
--- a/beat/web/reports/static/reports/app/services/reportService.js
+++ b/beat/web/reports/static/reports/app/services/reportService.js
@@ -28,6 +28,7 @@
  */
 angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterFactory', 'PlotService', 'reportFactory', 'UrlService', 'ErrorService', function(GroupsService, plotterFactory, PlotService, reportFactory, UrlService, ErrorService){
     const rs = {};
+    console.log('in reportsService');
 
     rs.isAnonymous = undefined;
     rs.isOwner = undefined;
@@ -43,7 +44,7 @@ angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterF
     // processed the report data received from the server,
     // and bootstraps the state of various services
     rs.processReport = (report) => {
-
+        console.log('in reportsService processReport');
         // useful info about the app
         rs.isAnonymous = report.anonymous;
         rs.isOwner = report.is_owner;
@@ -86,6 +87,7 @@ angular.module('reportApp').factory('ReportService', ['GroupsService', 'plotterF
     // fetch the report data using either the by-name or by-number scheme,
     // according to what URLService found
     rs.fetchReport = () => {
+        console.log('in reportsService fetchReport');
         const nameSeg = UrlService.getNameSegment();
         const numSeg = UrlService.getNumberSegment();
 
diff --git a/beat/web/reports/static/reports/app/services/urlService.js b/beat/web/reports/static/reports/app/services/urlService.js
index 861f52a65de39978167dcf88ea6ad543ba268fd6..a6503dc54f4cb8fc9081301ad3194892b2233731 100644
--- a/beat/web/reports/static/reports/app/services/urlService.js
+++ b/beat/web/reports/static/reports/app/services/urlService.js
@@ -26,6 +26,7 @@
  *  Helper functionality to generate URLs for the reports app
  */
 angular.module('reportApp').factory('UrlService', [function(){
+    console.log('in UrlService');
     // const path segments
     const experimentSegment = 'experiments/';
     const blockSegment = 'algorithms/';