diff --git a/frontend/src/activity/activity.services.js b/frontend/src/activity/activity.services.js
deleted file mode 100644
index 6e9c7e735b713052b7266ec2553986b6cf2130ce..0000000000000000000000000000000000000000
--- a/frontend/src/activity/activity.services.js
+++ /dev/null
@@ -1,16 +0,0 @@
-var ActivityServices = angular.module('metabase.activity.services', ['ngResource', 'ngCookies']);
-
-ActivityServices.factory('Activity', ['$resource', '$cookies', function($resource, $cookies) {
-    return $resource('/api/activity', {}, {
-        list: {
-            method: 'GET',
-            isArray: true
-        },
-
-        recent_views: {
-            url: '/api/activity/recent_views',
-            method: 'GET',
-            isArray: true
-        }
-    });
-}]);
diff --git a/frontend/src/admin/databases/databases.controllers.js b/frontend/src/admin/databases/databases.controllers.js
index 180f8bd72137951d2c778aa7562529cad321ec34..4fbc74c322437297a9fd75c82d5308512aeee1b1 100644
--- a/frontend/src/admin/databases/databases.controllers.js
+++ b/frontend/src/admin/databases/databases.controllers.js
@@ -5,7 +5,7 @@ import DatabaseList from "./components/DatabaseList.jsx";
 import DatabaseEdit from "./components/DatabaseEdit.jsx";
 
 
-var DatabasesControllers = angular.module('metabaseadmin.databases.controllers', ['metabase.metabase.services']);
+var DatabasesControllers = angular.module('metabaseadmin.databases.controllers', ['metabase.services']);
 
 DatabasesControllers.controller('DatabaseList', ['$scope', '$routeParams', 'Metabase', function($scope, $routeParams, Metabase) {
 
diff --git a/frontend/src/admin/metadata/components/MetadataEditor.jsx b/frontend/src/admin/metadata/components/MetadataEditor.jsx
index 9ac0f8991cda5376ecf707b29c439bed46467748..b6e00133d2fde93525fffe1a2740fc33e3733eda 100644
--- a/frontend/src/admin/metadata/components/MetadataEditor.jsx
+++ b/frontend/src/admin/metadata/components/MetadataEditor.jsx
@@ -1,4 +1,5 @@
 import React, { Component, PropTypes } from "react";
+import _ from "underscore";
 
 import MetadataHeader from './MetadataHeader.jsx';
 import MetadataTableList from './MetadataTableList.jsx';
@@ -23,6 +24,7 @@ export default class MetadataEditor extends Component {
         databaseId: PropTypes.number,
         databases: PropTypes.array.isRequired,
         selectDatabase: PropTypes.func.isRequired,
+        databaseMetadata: PropTypes.object,
         tableId: PropTypes.number,
         tables: PropTypes.object.isRequired,
         selectTable: PropTypes.func.isRequired,
@@ -63,7 +65,7 @@ export default class MetadataEditor extends Component {
     }
 
     render() {
-        var table = this.props.tables[this.props.tableId];
+        var table = (this.props.databaseMetadata) ? _.findWhere(this.props.databaseMetadata.tables, {id: this.props.tableId}) : null;
         var content;
         if (table) {
             if (this.state.isShowingSchema) {
@@ -100,7 +102,7 @@ export default class MetadataEditor extends Component {
                 <div className="MetadataEditor-main flex flex-row flex-full mt2">
                     <MetadataTableList
                         tableId={this.props.tableId}
-                        tables={this.props.tables}
+                        tables={(this.props.databaseMetadata) ? this.props.databaseMetadata.tables : []}
                         selectTable={this.props.selectTable}
                     />
                     {content}
diff --git a/frontend/src/admin/metadata/metadata.controllers.js b/frontend/src/admin/metadata/metadata.controllers.js
index 0c7e7480e1e2c2ca040d3c46d78a7b6ebc84cb6b..f8d8acaedbd3a02de5d9ce6d37df17afcf1c39a5 100644
--- a/frontend/src/admin/metadata/metadata.controllers.js
+++ b/frontend/src/admin/metadata/metadata.controllers.js
@@ -51,8 +51,8 @@ function($scope, $route, $routeParams, $location, $q, $timeout, databases, Metab
         $scope.tables = {};
         if ($scope.databaseId != null) {
             try {
-                await loadTableMetadata();
                 await loadIdFields();
+                await loadDatabaseMetadata();
                 $timeout(() => $scope.$digest());
             } catch (error) {
                 console.warn("error loading tables", error)
@@ -60,14 +60,10 @@ function($scope, $route, $routeParams, $location, $q, $timeout, databases, Metab
         }
     }, true);
 
-    async function loadTableMetadata() {
-        var tables = await Metabase.db_tables({ 'dbId': $scope.databaseId }).$promise;
-        await* tables.map(async function(table) {
-            $scope.tables[table.id] = await Metabase.table_query_metadata({
-                'tableId': table.id,
-                'include_sensitive_fields': true
-            }).$promise;
-            computeMetadataStrength($scope.tables[table.id]);
+    async function loadDatabaseMetadata() {
+        $scope.databaseMetadata = await Metabase.db_metadata({ 'dbId': $scope.databaseId }).$promise;
+        $scope.databaseMetadata.tables.map(function(table, index) {
+            table.metadataStrength = computeMetadataStrength(table);
         });
     }
 
@@ -94,7 +90,7 @@ function($scope, $route, $routeParams, $location, $q, $timeout, databases, Metab
     $scope.updateTable = function(table) {
         return Metabase.table_update(table).$promise.then(function(result) {
             _.each(result, (value, key) => { if (key.charAt(0) !== "$") { table[key] = value } });
-            computeMetadataStrength($scope.tables[table.id]);
+            table.metadataStrength = computeMetadataStrength(table);
             $timeout(() => $scope.$digest());
         });
     };
@@ -102,7 +98,8 @@ function($scope, $route, $routeParams, $location, $q, $timeout, databases, Metab
     $scope.updateField = function(field) {
         return Metabase.field_update(field).$promise.then(function(result) {
             _.each(result, (value, key) => { if (key.charAt(0) !== "$") { field[key] = value } });
-            computeMetadataStrength($scope.tables[field.table_id]);
+            let table = _.findWhere($scope.databaseMetadata.tables, {id: field.table_id});
+            table.metadataStrength = computeMetadataStrength(table);
             return loadIdFields();
         }).then(function() {
             $timeout(() => $scope.$digest());
@@ -126,7 +123,7 @@ function($scope, $route, $routeParams, $location, $q, $timeout, databases, Metab
             }
         });
 
-        table.metadataStrength = completed / total;
+        return (completed / total);
     }
 
     $scope.updateFieldSpecialType = async function(field) {
diff --git a/frontend/src/app.js b/frontend/src/app.js
index 47906c94bcaef820b3ce2e6972d7ee94ab591586..8bccc0487b5c5184113fd6aed3357e506f20df40 100644
--- a/frontend/src/app.js
+++ b/frontend/src/app.js
@@ -3,7 +3,6 @@ var Metabase = angular.module('metabase', [
     'ngRoute',
     'ngCookies',
     'ui.bootstrap', // bootstrap LIKE widgets via angular directives
-    'metabase.activity.services',
     'metabase.auth',
     'metabase.filters',
     'metabase.directives',
diff --git a/frontend/src/card/card.services.js b/frontend/src/card/card.services.js
index d69e850f86ceede870d935e2ff141224b5ec23c0..537e0fb8566f089aef32f7735cffad02b48bd806 100644
--- a/frontend/src/card/card.services.js
+++ b/frontend/src/card/card.services.js
@@ -5,84 +5,6 @@ import { normal, harmony } from 'metabase/lib/colors'
 // Card Services
 var CardServices = angular.module('metabase.card.services', ['ngResource', 'ngCookies']);
 
-CardServices.factory('Card', ['$resource', '$cookies', function($resource, $cookies) {
-    return $resource('/api/card/:cardId', {}, {
-        list: {
-            url: '/api/card/?f=:filterMode',
-            method: 'GET',
-            isArray: true
-        },
-        create: {
-            url: '/api/card',
-            method: 'POST',
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        get: {
-            method: 'GET',
-            params: {
-                cardId: '@cardId'
-            }
-        },
-        update: {
-            method: 'PUT',
-            params: {
-                cardId: '@id'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        delete: {
-            method: 'DELETE',
-            params: {
-                cardId: '@cardId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        isfavorite: {
-            url: '/api/card/:cardId/favorite',
-            method: 'GET',
-            params: {
-                cardId: '@cardId'
-            }
-        },
-        favorite: {
-            url: '/api/card/:cardId/favorite',
-            method: 'POST',
-            params: {
-                cardId: '@cardId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        unfavorite: {
-            url: '/api/card/:cardId/favorite',
-            method: 'DELETE',
-            params: {
-                cardId: '@cardId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        }
-    });
-}]);
-
 CardServices.service('VisualizationUtils', [function() {
     this.visualizationTypes = {
         scalar: {
diff --git a/frontend/src/dashboard/dashboard.module.js b/frontend/src/dashboard/dashboard.module.js
index 1f2b6ec3fd8481a0f7a79527fe8c02dcca6d4271..2f543640283a2dae68800079070a0710f27ff7a2 100644
--- a/frontend/src/dashboard/dashboard.module.js
+++ b/frontend/src/dashboard/dashboard.module.js
@@ -3,7 +3,6 @@ var Dashboard = angular.module('metabase.dashboard', [
     'ngRoute',
     'metabase.directives',
     'metabase.services',
-    'metabase.dashboard.services',
     'metabase.dashboard.controllers',
     'metabase.card.services'
 ]);
diff --git a/frontend/src/dashboard/dashboard.services.js b/frontend/src/dashboard/dashboard.services.js
deleted file mode 100644
index a573847f7eac5bf122c01aeb6f6aae9e17752ac9..0000000000000000000000000000000000000000
--- a/frontend/src/dashboard/dashboard.services.js
+++ /dev/null
@@ -1,49 +0,0 @@
-// Dashboard Services
-var DashboardServices = angular.module('metabase.dashboard.services', ['ngResource', 'ngCookies']);
-
-DashboardServices.factory('Dashboard', ['$resource', '$cookies', function($resource, $cookies) {
-    return $resource('/api/dashboard/:dashId', {}, {
-        list: {
-            url:'/api/dashboard?org=:orgId&f=:filterMode',
-            method:'GET',
-            isArray:true
-        },
-        create: {
-            url:'/api/dashboard',
-            method:'POST',
-            headers: {'X-CSRFToken': function() { return $cookies.csrftoken; }},
-        },
-        get: {
-            method:'GET',
-            params:{dashId:'@dashId'},
-        },
-        update: {
-            method:'PUT',
-            params:{dashId:'@id'},
-            headers: {'X-CSRFToken': function() { return $cookies.csrftoken; }},
-        },
-        delete: {
-            method:'DELETE',
-            params:{dashId:'@dashId'},
-            headers: {'X-CSRFToken': function() { return $cookies.csrftoken; }},
-        },
-        addcard: {
-            url:'/api/dashboard/:dashId/cards',
-            method:'POST',
-            params:{dashId:'@dashId'},
-            headers: {'X-CSRFToken': function() { return $cookies.csrftoken; }},
-        },
-        removecard: {
-            url:'/api/dashboard/:dashId/cards',
-            method:'DELETE',
-            params:{dashId:'@dashId'},
-            headers: {'X-CSRFToken': function() { return $cookies.csrftoken; }},
-        },
-        reposition_cards: {
-            url:'/api/dashboard/:dashId/reposition',
-            method:'POST',
-            params:{dashId:'@dashId'},
-            headers: {'X-CSRFToken': function() { return $cookies.csrftoken; }},
-        }
-    });
-}]);
diff --git a/frontend/src/metabase/metabase.services.js b/frontend/src/metabase/metabase.services.js
deleted file mode 100644
index 4bf55f2b0dfcd010e8ca698606eb7c897ba71f7e..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/metabase.services.js
+++ /dev/null
@@ -1,271 +0,0 @@
-// Metabase Services
-var MetabaseServices = angular.module('metabase.metabase.services', [
-    'ngResource',
-    'ngCookies',
-    'metabase.services'
-]);
-
-MetabaseServices.factory('Metabase', ['$resource', '$cookies', 'MetabaseCore', function($resource, $cookies, MetabaseCore) {
-    return $resource('/api/meta', {}, {
-        db_list: {
-            url: '/api/database/?org=:orgId',
-            method: 'GET',
-            isArray: true
-        },
-        db_create: {
-            url: '/api/database/',
-            method: 'POST',
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        db_add_sample_dataset: {
-            url: '/api/database/sample_dataset',
-            method: 'POST'
-        },
-        db_get: {
-            url: '/api/database/:dbId',
-            method: 'GET',
-            params: {
-                dbId: '@dbId'
-            }
-        },
-        db_update: {
-            url: '/api/database/:dbId',
-            method: 'PUT',
-            params: {
-                dbId: '@id'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        db_delete: {
-            url: '/api/database/:dbId',
-            method: 'DELETE',
-            params: {
-                dbId: '@dbId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        db_metadata: {
-            url: '/api/database/:dbId/metadata',
-            method: 'GET',
-            params: {
-                dbId: '@dbId'
-            }
-        },
-        db_tables: {
-            url: '/api/database/:dbId/tables',
-            method: 'GET',
-            params: {
-                dbId: '@dbId'
-            },
-            isArray: true
-        },
-        db_idfields: {
-            url: '/api/database/:dbId/idfields',
-            method: 'GET',
-            params: {
-                dbId: '@dbId'
-            },
-            isArray: true
-        },
-        db_autocomplete_suggestions: {
-            url: '/api/database/:dbId/autocomplete_suggestions?prefix=:prefix',
-            method: 'GET',
-            params: {
-                dbId: '@dbId'
-            },
-            isArray: true
-        },
-        db_sync_metadata: {
-            url: '/api/database/:dbId/sync',
-            method: 'POST',
-            params: {
-                dbId: '@dbId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        table_list: {
-            url: '/api/table/',
-            method: 'GET',
-            params: {
-                tableId: '@tableId'
-            },
-            isArray: true
-        },
-        table_get: {
-            url: '/api/table/:tableId',
-            method: 'GET',
-            params: {
-                tableId: '@tableId'
-            }
-        },
-        table_update: {
-            url: '/api/table/:tableId',
-            method: 'PUT',
-            params: {
-                tableId: '@id'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        table_fields: {
-            url: '/api/table/:tableId/fields',
-            method: 'GET',
-            params: {
-                tableId: '@tableId'
-            },
-            isArray: true
-        },
-        table_fks: {
-            url: '/api/table/:tableId/fks',
-            method: 'GET',
-            params: {
-                tableId: '@tableId'
-            },
-            isArray: true
-        },
-        table_reorder_fields: {
-            url: '/api/table/:tableId/reorder',
-            method: 'POST',
-            params: {
-                tableId: '@tableId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            },
-        },
-        table_query_metadata: {
-            url: '/api/table/:tableId/query_metadata',
-            method: 'GET',
-            params: {
-                dbId: '@tableId'
-            }
-        },
-        table_sync_metadata: {
-            url: '/api/table/:tableId/sync',
-            method: 'POST',
-            params: {
-                tableId: '@tableId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        field_get: {
-            url: '/api/field/:fieldId',
-            method: 'GET',
-            params: {
-                fieldId: '@fieldId'
-            }
-        },
-        field_summary: {
-            url: '/api/field/:fieldId/summary',
-            method: 'GET',
-            params: {
-                fieldId: '@fieldId'
-            },
-            isArray: true
-        },
-        field_values: {
-            url: '/api/field/:fieldId/values',
-            method: 'GET',
-            params: {
-                fieldId: '@fieldId'
-            }
-        },
-        field_value_map_update: {
-            url: '/api/field/:fieldId/value_map_update',
-            method: 'POST',
-            params: {
-                fieldId: '@fieldId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        field_update: {
-            url: '/api/field/:fieldId',
-            method: 'PUT',
-            params: {
-                fieldId: '@id'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        field_foreignkeys: {
-            url: '/api/field/:fieldId/foreignkeys',
-            method: 'GET',
-            params: {
-                fieldId: '@fieldId'
-            },
-            isArray: true
-        },
-        field_addfk: {
-            url: '/api/field/:fieldId/foreignkeys',
-            method: 'POST',
-            params: {
-                fieldId: '@fieldId'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        },
-        dataset: {
-            url: '/api/dataset',
-            method: 'POST',
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            }
-        }
-    });
-}]);
-
-
-
-MetabaseServices.factory('ForeignKey', ['$resource', '$cookies', function($resource, $cookies) {
-    return $resource('/api/foreignkey/:fkID', {}, {
-        delete: {
-            method: 'DELETE',
-            params: {
-                fkID: '@fkID'
-            },
-            headers: {
-                'X-CSRFToken': function() {
-                    return $cookies.csrftoken;
-                }
-            },
-        },
-
-    });
-}]);
diff --git a/frontend/src/services.js b/frontend/src/services.js
index 4d8bc5626b7fb8de203dc849666de224985450ba..71f8b817a0a7874dbffcd4b6a309d827fad93734 100644
--- a/frontend/src/services.js
+++ b/frontend/src/services.js
@@ -259,9 +259,342 @@ MetabaseServices.service('MetabaseCore', ['User', function(User) {
 }]);
 
 
-// User Services
+// API Services
 var CoreServices = angular.module('metabase.core.services', ['ngResource', 'ngCookies']);
 
+CoreServices.factory('Activity', ['$resource', '$cookies', function($resource, $cookies) {
+    return $resource('/api/activity', {}, {
+        list: {
+            method: 'GET',
+            isArray: true
+        },
+        recent_views: {
+            url: '/api/activity/recent_views',
+            method: 'GET',
+            isArray: true
+        }
+    });
+}]);
+
+CoreServices.factory('Card', ['$resource', '$cookies', function($resource, $cookies) {
+    return $resource('/api/card/:cardId', {}, {
+        list: {
+            url: '/api/card/?f=:filterMode',
+            method: 'GET',
+            isArray: true
+        },
+        create: {
+            url: '/api/card',
+            method: 'POST'
+        },
+        get: {
+            method: 'GET',
+            params: {
+                cardId: '@cardId'
+            }
+        },
+        update: {
+            method: 'PUT',
+            params: {
+                cardId: '@id'
+            }
+        },
+        delete: {
+            method: 'DELETE',
+            params: {
+                cardId: '@cardId'
+            }
+        },
+        isfavorite: {
+            url: '/api/card/:cardId/favorite',
+            method: 'GET',
+            params: {
+                cardId: '@cardId'
+            }
+        },
+        favorite: {
+            url: '/api/card/:cardId/favorite',
+            method: 'POST',
+            params: {
+                cardId: '@cardId'
+            }
+        },
+        unfavorite: {
+            url: '/api/card/:cardId/favorite',
+            method: 'DELETE',
+            params: {
+                cardId: '@cardId'
+            }
+        }
+    });
+}]);
+
+CoreServices.factory('Dashboard', ['$resource', '$cookies', function($resource, $cookies) {
+    return $resource('/api/dashboard/:dashId', {}, {
+        list: {
+            url:'/api/dashboard?org=:orgId&f=:filterMode',
+            method:'GET',
+            isArray:true
+        },
+        create: {
+            url:'/api/dashboard',
+            method:'POST'
+        },
+        get: {
+            method:'GET',
+            params:{dashId:'@dashId'},
+        },
+        update: {
+            method:'PUT',
+            params:{dashId:'@id'}
+        },
+        delete: {
+            method:'DELETE',
+            params:{dashId:'@dashId'}
+        },
+        addcard: {
+            url:'/api/dashboard/:dashId/cards',
+            method:'POST',
+            params:{dashId:'@dashId'}
+        },
+        removecard: {
+            url:'/api/dashboard/:dashId/cards',
+            method:'DELETE',
+            params:{dashId:'@dashId'}
+        },
+        reposition_cards: {
+            url:'/api/dashboard/:dashId/reposition',
+            method:'POST',
+            params:{dashId:'@dashId'}
+        }
+    });
+}]);
+
+CoreServices.factory('ForeignKey', ['$resource', '$cookies', function($resource, $cookies) {
+    return $resource('/api/foreignkey/:fkID', {}, {
+        delete: {
+            method: 'DELETE',
+            params: {
+                fkID: '@fkID'
+            }
+        }
+    });
+}]);
+
+CoreServices.factory('Metabase', ['$resource', '$cookies', 'MetabaseCore', function($resource, $cookies, MetabaseCore) {
+    return $resource('/api/meta', {}, {
+        db_list: {
+            url: '/api/database/?org=:orgId',
+            method: 'GET',
+            isArray: true
+        },
+        db_create: {
+            url: '/api/database/',
+            method: 'POST'
+        },
+        db_add_sample_dataset: {
+            url: '/api/database/sample_dataset',
+            method: 'POST'
+        },
+        db_get: {
+            url: '/api/database/:dbId',
+            method: 'GET',
+            params: {
+                dbId: '@dbId'
+            }
+        },
+        db_update: {
+            url: '/api/database/:dbId',
+            method: 'PUT',
+            params: {
+                dbId: '@id'
+            }
+        },
+        db_delete: {
+            url: '/api/database/:dbId',
+            method: 'DELETE',
+            params: {
+                dbId: '@dbId'
+            }
+        },
+        db_metadata: {
+            url: '/api/database/:dbId/metadata',
+            method: 'GET',
+            params: {
+                dbId: '@dbId'
+            }
+        },
+        db_tables: {
+            url: '/api/database/:dbId/tables',
+            method: 'GET',
+            params: {
+                dbId: '@dbId'
+            },
+            isArray: true
+        },
+        db_idfields: {
+            url: '/api/database/:dbId/idfields',
+            method: 'GET',
+            params: {
+                dbId: '@dbId'
+            },
+            isArray: true
+        },
+        db_autocomplete_suggestions: {
+            url: '/api/database/:dbId/autocomplete_suggestions?prefix=:prefix',
+            method: 'GET',
+            params: {
+                dbId: '@dbId'
+            },
+            isArray: true
+        },
+        db_sync_metadata: {
+            url: '/api/database/:dbId/sync',
+            method: 'POST',
+            params: {
+                dbId: '@dbId'
+            }
+        },
+        table_list: {
+            url: '/api/table/',
+            method: 'GET',
+            params: {
+                tableId: '@tableId'
+            },
+            isArray: true
+        },
+        table_get: {
+            url: '/api/table/:tableId',
+            method: 'GET',
+            params: {
+                tableId: '@tableId'
+            }
+        },
+        table_update: {
+            url: '/api/table/:tableId',
+            method: 'PUT',
+            params: {
+                tableId: '@id'
+            }
+        },
+        table_fields: {
+            url: '/api/table/:tableId/fields',
+            method: 'GET',
+            params: {
+                tableId: '@tableId'
+            },
+            isArray: true
+        },
+        table_fks: {
+            url: '/api/table/:tableId/fks',
+            method: 'GET',
+            params: {
+                tableId: '@tableId'
+            },
+            isArray: true
+        },
+        table_reorder_fields: {
+            url: '/api/table/:tableId/reorder',
+            method: 'POST',
+            params: {
+                tableId: '@tableId'
+            }
+        },
+        table_query_metadata: {
+            url: '/api/table/:tableId/query_metadata',
+            method: 'GET',
+            params: {
+                dbId: '@tableId'
+            }
+        },
+        table_sync_metadata: {
+            url: '/api/table/:tableId/sync',
+            method: 'POST',
+            params: {
+                tableId: '@tableId'
+            }
+        },
+        field_get: {
+            url: '/api/field/:fieldId',
+            method: 'GET',
+            params: {
+                fieldId: '@fieldId'
+            }
+        },
+        field_summary: {
+            url: '/api/field/:fieldId/summary',
+            method: 'GET',
+            params: {
+                fieldId: '@fieldId'
+            },
+            isArray: true
+        },
+        field_values: {
+            url: '/api/field/:fieldId/values',
+            method: 'GET',
+            params: {
+                fieldId: '@fieldId'
+            }
+        },
+        field_value_map_update: {
+            url: '/api/field/:fieldId/value_map_update',
+            method: 'POST',
+            params: {
+                fieldId: '@fieldId'
+            }
+        },
+        field_update: {
+            url: '/api/field/:fieldId',
+            method: 'PUT',
+            params: {
+                fieldId: '@id'
+            }
+        },
+        field_foreignkeys: {
+            url: '/api/field/:fieldId/foreignkeys',
+            method: 'GET',
+            params: {
+                fieldId: '@fieldId'
+            },
+            isArray: true
+        },
+        field_addfk: {
+            url: '/api/field/:fieldId/foreignkeys',
+            method: 'POST',
+            params: {
+                fieldId: '@fieldId'
+            }
+        },
+        dataset: {
+            url: '/api/dataset',
+            method: 'POST'
+        }
+    });
+}]);
+
+CoreServices.factory('Revision', ['$resource', function($resource) {
+    return $resource('/api/revision', {}, {
+        list: {
+            url: '/api/revision',
+            method: 'GET',
+            isArray: true,
+            params: {
+                'entity': '@entity',
+                'id': '@id'
+            }
+        },
+        revert: {
+            url: '/api/revision/revert',
+            method: 'POST',
+            params: {
+                'entity': '@entity',
+                'id': '@id',
+                'revision_id': '@revision_id'
+            }
+        }
+    });
+}]);
+
 CoreServices.factory('Session', ['$resource', '$cookies', function($resource, $cookies) {
     return $resource('/api/session/', {}, {
         create: {
@@ -290,6 +623,43 @@ CoreServices.factory('Session', ['$resource', '$cookies', function($resource, $c
     });
 }]);
 
+CoreServices.factory('Settings', ['$resource', function($resource) {
+    return $resource('/api/setting', {}, {
+        list: {
+            url: '/api/setting',
+            method: 'GET',
+            isArray: true,
+        },
+        // POST endpoint handles create + update in this case
+        put: {
+            url: '/api/setting/:key',
+            method: 'PUT',
+            params: {
+                key: '@key'
+            }
+        },
+        delete: {
+            url: '/api/setting/:key',
+            method: 'DELETE',
+            params: {
+                key: '@key'
+            }
+        }
+    });
+}]);
+
+CoreServices.factory('Setup', ['$resource', '$cookies', function($resource, $cookies) {
+    return $resource('/api/setup/', {}, {
+        create: {
+            method: 'POST'
+        },
+        validate_db: {
+            url: '/api/setup/validate',
+            method: 'POST'
+        }
+    });
+}]);
+
 CoreServices.factory('User', ['$resource', '$cookies', function($resource, $cookies) {
     return $resource('/api/user/:userId', {}, {
         create: {
@@ -343,57 +713,6 @@ CoreServices.factory('User', ['$resource', '$cookies', function($resource, $cook
     });
 }]);
 
-CoreServices.factory('Settings', ['$resource', function($resource) {
-    return $resource('/api/setting', {}, {
-        list: {
-            url: '/api/setting',
-            method: 'GET',
-            isArray: true,
-        },
-
-        // POST endpoint handles create + update in this case
-        put: {
-            url: '/api/setting/:key',
-            method: 'PUT',
-            params: {
-                key: '@key'
-            }
-        },
-
-        delete: {
-            url: '/api/setting/:key',
-            method: 'DELETE',
-            params: {
-                key: '@key'
-            }
-        }
-    });
-}]);
-
-CoreServices.factory('Revision', ['$resource', function($resource) {
-    return $resource('/api/revision', {}, {
-        list: {
-            url: '/api/revision',
-            method: 'GET',
-            isArray: true,
-            params: {
-                'entity': '@entity',
-                'id': '@id'
-            }
-        },
-
-        revert: {
-            url: '/api/revision/revert',
-            method: 'POST',
-            params: {
-                'entity': '@entity',
-                'id': '@id',
-                'revision_id': '@revision_id'
-            }
-        }
-    });
-}]);
-
 CoreServices.factory('Util', ['$resource', '$cookies', function($resource, $cookies) {
     return $resource('/api/util/', {}, {
         password_check: {
diff --git a/frontend/src/setup/setup.controllers.js b/frontend/src/setup/setup.controllers.js
index d3e68ff42ac1d3ac276a862bdb9b708fb03a38b1..f1e5a4dde42a59222bceeaa3a0d3c42443be1a35 100644
--- a/frontend/src/setup/setup.controllers.js
+++ b/frontend/src/setup/setup.controllers.js
@@ -16,7 +16,7 @@ const finalCreateStore = compose(
 const reducer = combineReducers(reducers);
 
 
-var SetupControllers = angular.module('metabase.setup.controllers', ['metabase.setup.services']);
+var SetupControllers = angular.module('metabase.setup.controllers', ['metabase.services']);
 SetupControllers.controller('SetupController', ['$scope', '$location', '$timeout', 'ipCookie', function($scope, $location, $timeout, ipCookie) {
     $scope.Component = SetupApp;
     $scope.props = {
diff --git a/frontend/src/setup/setup.services.js b/frontend/src/setup/setup.services.js
deleted file mode 100644
index d5e5297614f63061841ea1f978da5c99cbe456f8..0000000000000000000000000000000000000000
--- a/frontend/src/setup/setup.services.js
+++ /dev/null
@@ -1,15 +0,0 @@
-var SetupServices = angular.module('metabase.setup.services', ['ngResource', 'ngCookies']);
-
-SetupServices.factory('Setup', ['$resource', '$cookies', function($resource, $cookies) {
-    return $resource('/api/setup/', {}, {
-        create: {
-            method: 'POST'
-        },
-
-        validate_db: {
-            url: '/api/setup/validate',
-            method: 'POST'
-        }
-    });
-}]);
-
diff --git a/frontend/test/unit/services.spec.js b/frontend/test/unit/services.spec.js
index 940edfdd053cfcf82adefaec9ff75aaecb5b6201..a62fbb60749b120022a044140259d4d80cbb3dc8 100644
--- a/frontend/test/unit/services.spec.js
+++ b/frontend/test/unit/services.spec.js
@@ -1,8 +1,7 @@
 import 'metabase/services';
-import 'metabase/metabase/metabase.services';
 
-describe('metabase.metabase.services', function() {
-    beforeEach(angular.mock.module('metabase.metabase.services'));
+describe('metabase.services', function() {
+    beforeEach(angular.mock.module('metabase.services'));
 
     describe('Metabase', function() {
         it('should return empty list of databases', inject(function(Metabase, $httpBackend) {
diff --git a/src/metabase/driver/sqlserver.clj b/src/metabase/driver/sqlserver.clj
index 75bb8492850eebb19b740f898e21eeb3ba6e7fcb..acb9b9ef27897f876d3ad9a0ef6d5288827e13a3 100644
--- a/src/metabase/driver/sqlserver.clj
+++ b/src/metabase/driver/sqlserver.clj
@@ -47,13 +47,15 @@
    :xml              :UnknownField
    (keyword "int identity") :IntegerField}) ; auto-incrementing integer (ie pk) field
 
-(defn- connection-details->spec [details]
+(defn- connection-details->spec [{:keys [instance], :as details}]
   (-> (kdb/mssql details)
       ;; swap out Microsoft Driver details for jTDS ones
       (assoc :classname   "net.sourceforge.jtds.jdbc.Driver"
              :subprotocol "jtds:sqlserver")
       ;; adjust the connection URL to match up with the jTDS format (see http://jtds.sourceforge.net/faq.html#urlFormat)
-      (update :subname #(s/replace % #";database=" "/"))))
+      ;; and add the ;instance= option if applicable
+      (update :subname #(cond-> (s/replace % #";database=" "/")
+                          (seq instance) (str ";instance=" instance)))))
 
 ;; See also the [jTDS SQL <-> Java types table](http://jtds.sourceforge.net/typemap.html)
 (defn- date [unit field-or-value]
@@ -114,15 +116,18 @@
   (-> (sql-driver {:driver-name               "SQL Server"
                    :details-fields            [{:name         "host"
                                                 :display-name "Host"
-                                                :default "localhost"}
+                                                :default      "localhost"}
                                                {:name         "port"
                                                 :display-name "Port"
                                                 :type         :integer
                                                 :default      1433}
-                                               {:name         "dbname"
+                                               {:name         "db"
                                                 :display-name "Database name"
-                                                :placeholder  "birds_of_the_word"
+                                                :placeholder  "BirdsOfTheWorld"
                                                 :required     true}
+                                               {:name         "instance"
+                                                :display-name "Database instance name"
+                                                :placeholder  "N/A"}
                                                {:name         "user"
                                                 :display-name "Database username"
                                                 :placeholder  "What username do you use to login to the database?"
diff --git a/src/metabase/models/field_values.clj b/src/metabase/models/field_values.clj
index 2cffb9b11342db9984d477b2951e83ee71260530..bca255ecb3e14577929741536e76731c56ab70c6 100644
--- a/src/metabase/models/field_values.clj
+++ b/src/metabase/models/field_values.clj
@@ -33,6 +33,7 @@
          (contains? field :base_type)
          (contains? field :special_type)]}
   (and (not= (keyword field_type) :sensitive)
+       (not (contains? #{:DateField :DateTimeField :TimeField} (keyword base_type)))
        (or (contains? #{:category :city :state :country} (keyword special_type))
            (= (keyword base_type) :BooleanField))))
 
diff --git a/test/metabase/api/table_test.clj b/test/metabase/api/table_test.clj
index 9d5462b85286f11b96880c62d6fb9d3af7b16685..30d2ca68e19ce4def613ccc884e393c76c542873 100644
--- a/test/metabase/api/table_test.clj
+++ b/test/metabase/api/table_test.clj
@@ -292,10 +292,7 @@
        :active          true
        :id              (id :users)
        :db_id           (id)
-       :field_values    {(keyword (str (id :users :last_login)))
-                         user-last-login-date-strs
-
-                         (keyword (str (id :users :name)))
+       :field_values    {(keyword (str (id :users :name)))
                          ["Broen Olujimi"
                           "Conchúr Tihomir"
                           "Dwight Gresham"
@@ -390,10 +387,7 @@
        :active          true
        :id              (id :users)
        :db_id           (id)
-       :field_values    {(keyword (str (id :users :last_login)))
-                         user-last-login-date-strs
-
-                         (keyword (str (id :users :name)))
+       :field_values    {(keyword (str (id :users :name)))
                          ["Broen Olujimi"
                           "Conchúr Tihomir"
                           "Dwight Gresham"
diff --git a/test/metabase/models/field_test.clj b/test/metabase/models/field_test.clj
index 05bb383ab55ad1cf11b88e23d78484e4f178e88c..15f299d48d19859fd412d14f2c2aec81588e746d 100644
--- a/test/metabase/models/field_test.clj
+++ b/test/metabase/models/field_test.clj
@@ -5,6 +5,60 @@
                              [field-values :refer :all])
             [metabase.test.data :refer :all]))
 
+
+;; field-should-have-field-values?
+
+;; sensitive fields should always be excluded
+(expect false (field-should-have-field-values? {:base_type    :BooleanField
+                                                :special_type :category
+                                                :field_type   :sensitive}))
+;; date/time based fields should always be excluded
+(expect false (field-should-have-field-values? {:base_type    :DateField
+                                                :special_type :category
+                                                :field_type   :dimension}))
+(expect false (field-should-have-field-values? {:base_type    :DateTimeField
+                                                :special_type :category
+                                                :field_type   :dimension}))
+(expect false (field-should-have-field-values? {:base_type    :TimeField
+                                                :special_type :category
+                                                :field_type   :dimension}))
+;; most special types should be excluded
+(expect false (field-should-have-field-values? {:base_type    :CharField
+                                                :special_type :image
+                                                :field_type   :dimension}))
+(expect false (field-should-have-field-values? {:base_type    :CharField
+                                                :special_type :id
+                                                :field_type   :dimension}))
+(expect false (field-should-have-field-values? {:base_type    :CharField
+                                                :special_type :fk
+                                                :field_type   :dimension}))
+(expect false (field-should-have-field-values? {:base_type    :CharField
+                                                :special_type :latitude
+                                                :field_type   :dimension}))
+(expect false (field-should-have-field-values? {:base_type    :CharField
+                                                :special_type :number
+                                                :field_type   :dimension}))
+(expect false (field-should-have-field-values? {:base_type    :CharField
+                                                :special_type :timestamp_milliseconds
+                                                :field_type   :dimension}))
+;; boolean fields + category/city/state/country fields are g2g
+(expect true (field-should-have-field-values? {:base_type    :BooleanField
+                                               :special_type :number
+                                               :field_type   :dimension}))
+(expect true (field-should-have-field-values? {:base_type    :CharField
+                                               :special_type :category
+                                               :field_type   :dimension}))
+(expect true (field-should-have-field-values? {:base_type    :TextField
+                                               :special_type :city
+                                               :field_type   :dimension}))
+(expect true (field-should-have-field-values? {:base_type    :TextField
+                                               :special_type :state
+                                               :field_type   :dimension}))
+(expect true (field-should-have-field-values? {:base_type    :TextField
+                                               :special_type :country
+                                               :field_type   :dimension}))
+
+
 ;; Check that setting a Field's special_type to :category will cause a corresponding FieldValues to be created asynchronously
 (expect
     [nil