diff --git a/package-lock.json b/package-lock.json
index 85a59a66..84f77334 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2800,6 +2800,15 @@
         "@types/testing-library__react": "^9.1.2"
       }
     },
+    "@toast-ui/editor": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/@toast-ui/editor/-/editor-2.5.1.tgz",
+      "integrity": "sha512-LVNo/YaNItUemEaRFvFAVn7w/0U7yxEheMdn6GEGxqo727rRZD1MH7OTDVq6NeQ+P93VwFpa0i9GGRBhNNEbPQ==",
+      "requires": {
+        "@types/codemirror": "0.0.71",
+        "codemirror": "^5.48.4"
+      }
+    },
     "@types/anymatch": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/@types/anymatch/-/anymatch-1.3.1.tgz",
@@ -2847,6 +2856,19 @@
         "@babel/types": "^7.3.0"
       }
     },
+    "@types/codemirror": {
+      "version": "0.0.71",
+      "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.71.tgz",
+      "integrity": "sha512-b2oEEnno1LIGKMR7uBEsr40al1UijF1HEpRn0+Yf1xOLl24iQgB7DBpZVMM7y54G5wCNoclDrRO65E6KHPNO2w==",
+      "requires": {
+        "@types/tern": "*"
+      }
+    },
+    "@types/estree": {
+      "version": "0.0.46",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.46.tgz",
+      "integrity": "sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg=="
+    },
     "@types/glob": {
       "version": "7.1.3",
       "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
@@ -2991,6 +3013,14 @@
       "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==",
       "dev": true
     },
+    "@types/tern": {
+      "version": "0.23.3",
+      "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.3.tgz",
+      "integrity": "sha512-imDtS4TAoTcXk0g7u4kkWqedB3E4qpjXzCpD2LU5M5NAXHzCDsypyvXSaG7mM8DKYkCRa7tFp4tS/lp/Wo7Q3w==",
+      "requires": {
+        "@types/estree": "*"
+      }
+    },
     "@types/testing-library__dom": {
       "version": "6.14.0",
       "resolved": "https://registry.npmjs.org/@types/testing-library__dom/-/testing-library__dom-6.14.0.tgz",
@@ -4942,6 +4972,11 @@
       "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
       "dev": true
     },
+    "codemirror": {
+      "version": "5.59.3",
+      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.59.3.tgz",
+      "integrity": "sha512-p1d4BjmBBssgnEGtQeWvE5PdiDffqZjiJ77h2FZ2J2BpW9qdOzf6v7IQscyE+TgyKBQS3PpsYimfEDNgcNRZGQ=="
+    },
     "collect-v8-coverage": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
diff --git a/src/components/AsyncSelect/index.jsx b/src/components/AsyncSelect/index.jsx
new file mode 100644
index 00000000..269ad803
--- /dev/null
+++ b/src/components/AsyncSelect/index.jsx
@@ -0,0 +1,111 @@
+/**
+ * AsyncSelect
+ *
+ * A wrapper for react-select's AsyncCreatableSelect.
+ */
+import React from "react";
+import PT from "prop-types";
+import AsyncCreatableSelect from "react-select/async-creatable";
+import "./styles.module.scss";
+
+const AsyncSelect = (props) => {
+  const customStyles = {
+    control: (provided, state) => ({
+      ...provided,
+      minHeight: "40px",
+      border: "1px solid #aaaaab",
+      borderColor: state.isFocused ? "#55a5ff" : "#aaaaab",
+      boxShadow: state.isFocused ? "0 0 2px 1px #cee6ff" : provided.boxShadow,
+    }),
+    menu: (provided) => ({
+      ...provided,
+      minHeight: "40px",
+      zIndex: 10,
+    }),
+    valueContainer: (provided) => ({
+      ...provided,
+      padding: "2px 6px",
+    }),
+    input: (provided) => ({
+      ...provided,
+      margin: "0px",
+      height: "auto",
+      padding: "0",
+    }),
+    indicatorSeparator: () => ({
+      display: "none",
+    }),
+    indicatorsContainer: (provided) => ({
+      ...provided,
+      height: "auto",
+    }),
+    option: (provided) => ({
+      ...provided,
+      minHeight: "32px",
+    }),
+    placeholder: (provided) => ({
+      ...provided,
+      color: "#AAAAAA",
+      fontFamily: "Roboto",
+      fontSize: "14px",
+      lineHeight: "22px",
+      textAlign: "left",
+      fontWeight: "400",
+    }),
+    multiValue: (provided) => ({
+      ...provided,
+      margin: "3px 3px",
+      color: "#AAAAAA",
+      fontFamily: "Roboto",
+      fontSize: "14px",
+      lineHeight: "22px",
+      textAlign: "left",
+      borderRadius: "5px",
+    }),
+    dropdownIndicator: () => ({
+      display: "none",
+    }),
+  };
+
+  return (
+    <div styleName="select-wrapper">
+      <AsyncCreatableSelect
+        value={props.value}
+        styles={customStyles}
+        onChange={props.onChange}
+        styleName={props.error ? "error" : ""}
+        isMulti={props.isMulti}
+        onBlur={props.onBlur}
+        onFocus={props.onFocus}
+        placeholder={props.placeholder}
+        onInputChange={props.onInputChange}
+        noOptionsMessage={() => props.noOptionsText}
+        loadingMessage={() => props.loadingText}
+        isDisabled={props.disabled}
+        cacheOptions={props.cacheOptions}
+        loadOptions={props.loadOptions}
+        defaultOptions={props.defaultOptions}
+      />
+    </div>
+  )
+}
+
+AsyncSelect.propTypes = {
+  value: PT.string,
+  onChange: PT.func,
+  placeholder: PT.string,
+  error: PT.string,
+  isMulti: PT.bool,
+  onBlur: PT.func,
+  onFocus: PT.func,
+  onInputChange: PT.func,
+  cacheOptions: PT.bool,
+  onInputChange: PT.func,
+  noOptionsText: PT.string,
+  loadingText: PT.string,
+  loadOptions: PT.func,
+  defaultOptions: PT.bool || PT.array,
+  disabled: PT.bool,
+}
+
+export default AsyncSelect;
\ No newline at end of file
diff --git a/src/components/AsyncSelect/styles.module.scss b/src/components/AsyncSelect/styles.module.scss
new file mode 100644
index 00000000..96ffd0d3
--- /dev/null
+++ b/src/components/AsyncSelect/styles.module.scss
@@ -0,0 +1,18 @@
+.error {
+  :first-child {
+    border-color: #ff5b52;
+  }
+}
+
+.select-wrapper {
+  input {
+    border: none !important;
+    box-shadow: none !important;
+    transition: none !important;
+    height: 28px;
+  }
+}
+
+.react-select__option {
+  min-height: 32px;
+}
diff --git a/src/components/ReactSelect/index.jsx b/src/components/ReactSelect/index.jsx
index 567b70b2..1101fe59 100644
--- a/src/components/ReactSelect/index.jsx
+++ b/src/components/ReactSelect/index.jsx
@@ -70,38 +70,20 @@ const ReactSelect = (props) => {
 
   return (
     <div styleName="select-wrapper">
-      {props.isCreatable ? (
-        <CreatableSelect
-          value={props.value}
-          styles={customStyles}
-          onChange={props.onChange}
-          options={props.options}
-          styleName={props.error ? "error" : ""}
-          isMulti={props.isMulti}
-          onBlur={props.onBlur}
-          onFocus={props.onFocus}
-          placeholder={props.placeholder}
-          onInputChange={props.onInputChange}
-          noOptionsMessage={() => props.noOptionsText}
-          createOptionPosition="first"
-          isDisabled={props.disabled}
-        />
-      ) : (
-        <Select
-          value={props.value}
-          styles={customStyles}
-          onChange={props.onChange}
-          options={props.options}
-          styleName={props.error ? "error" : ""}
-          isMulti={props.isMulti}
-          onBlur={props.onBlur}
-          onFocus={props.onFocus}
-          placeholder={props.placeholder}
-          onInputChange={props.onInputChange}
-          noOptionsMessage={() => props.noOptionsText}
-          isDisabled={props.disabled}
-        />
-      )}
+      <Select
+        value={props.value}
+        styles={customStyles}
+        onChange={props.onChange}
+        options={props.options}
+        styleName={props.error ? "error" : ""}
+        isMulti={props.isMulti}
+        onBlur={props.onBlur}
+        onFocus={props.onFocus}
+        placeholder={props.placeholder}
+        onInputChange={props.onInputChange}
+        noOptionsMessage={() => props.noOptionsText}
+        isDisabled={props.disabled}
+      />
     </div>
   );
 };
@@ -121,7 +103,6 @@ ReactSelect.propTypes = {
       label: PT.string.isRequired,
     }).isRequired
   ),
-  isCreatable: PT.bool,
   noOptionsText: PT.string,
   disabled: PT.bool,
 };
diff --git a/src/routes/TeamAccess/actions/index.js b/src/routes/TeamAccess/actions/index.js
index 4dd31276..8b062e39 100644
--- a/src/routes/TeamAccess/actions/index.js
+++ b/src/routes/TeamAccess/actions/index.js
@@ -6,7 +6,6 @@ import {
   getTeamMembers,
   getTeamInvitees,
   deleteTeamMember,
-  getMemberSuggestions,
   postMembers,
 } from "services/teams";
 import { ACTION_TYPE } from "constants";
@@ -74,31 +73,6 @@ export const removeTeamMember = (teamId, memberId) => ({
   },
 });
 
-/**
- * Loads suggestions for invites
- *
- * @param {string} fragment
- *
- * @returns {Promise<object[]>} list of suggestions or error
- */
-export const loadSuggestions = (fragment) => ({
-  type: ACTION_TYPE.LOAD_MEMBERS_SUGGESTIONS,
-  payload: async () => {
-    const res = await getMemberSuggestions(fragment);
-    return res.data.result.content;
-  },
-  meta: {
-    fragment,
-  },
-});
-
-/**
- * Clears invite suggestions
- */
-export const clearSuggestions = () => ({
-  type: ACTION_TYPE.CLEAR_MEMBERS_SUGGESTIONS,
-});
-
 /**
  * Adds members to team
  *
diff --git a/src/routes/TeamAccess/components/AddModal/index.jsx b/src/routes/TeamAccess/components/AddModal/index.jsx
index 9ab5b696..71b22a57 100644
--- a/src/routes/TeamAccess/components/AddModal/index.jsx
+++ b/src/routes/TeamAccess/components/AddModal/index.jsx
@@ -1,17 +1,46 @@
 import React, { useCallback, useState } from "react";
 import _ from "lodash";
 import PT from "prop-types";
-import { useDispatch, useSelector } from "react-redux";
+import { useDispatch } from "react-redux";
 import { toastr } from "react-redux-toastr";
-import { loadSuggestions, clearSuggestions, addMembers } from "../../actions";
+import { addMembers } from "../../actions";
 import Button from "components/Button";
 import BaseModal from "components/BaseModal";
-import ReactSelect from "components/ReactSelect";
+import AsyncSelect from "components/AsyncSelect";
 import "./styles.module.scss";
 import { formatPlural } from "utils/format";
+import { getMemberSuggestions } from "services/teams";
 
-// Minimum length of input for suggestions to trigger
-const SUGGESTION_TRIGGER_LENGTH = 3;
+/**
+ * Fetches suggestions based on input in select box
+ * @param {string} inputVal Input from select
+ * 
+ * @returns {Promise<Array>} A promise that resolves to list of suggested users 
+ */
+const loadSuggestions = inputVal => {
+  return getMemberSuggestions(inputVal)
+    .then(res => {
+      const users = _.get(res, "data.result.content", []);
+      return users.map(user => ({
+        label: user.handle,
+        value: user.handle
+      }))
+    })
+    .catch(() => {
+      console.warn("could not get suggestions");
+      return [];
+    }) 
+}
+
+/**
+ * Function to call if user does not have permission to see suggestions
+ * @returns {Promise<Array>} Promise resolving to empty array
+ */
+const emptySuggestions = () => {
+  return new Promise(resolve => {
+    resolve([]);
+  })
+}
 
 /**
  * Filters selected members, keeping those who could not be added to team
@@ -59,21 +88,8 @@ const AddModal = ({ open, onClose, teamId, validateAdds, showSuggestions }) => {
   const [validationError, setValidationError] = useState(false);
   const [responseErrors, setResponseErrors] = useState([]);
   const [selectedMembers, setSelectedMembers] = useState([]);
-  const options = useSelector((state) =>
-    state.teamMembers.suggestions.map((sugg) => ({
-      label: sugg.handle,
-      value: sugg.handle,
-    }))
-  );
-  const dispatch = useDispatch();
 
-  const debouncedLoadSuggestions = _.debounce(
-    (arg) => {
-      dispatch(loadSuggestions(arg));
-    },
-    500,
-    { leading: true }
-  );
+  const dispatch = useDispatch();
 
   const handleClose = useCallback(() => {
     setSelectedMembers([]);
@@ -142,17 +158,8 @@ const AddModal = ({ open, onClose, teamId, validateAdds, showSuggestions }) => {
         onUpdate([...selectedMembers, { label: val, value: val }]);
         return "";
       }
-
-      // load suggestions if role allows
-      if (showSuggestions) {
-        if (val.length >= SUGGESTION_TRIGGER_LENGTH) {
-          debouncedLoadSuggestions(val);
-        } else {
-          dispatch(clearSuggestions());
-        }
-      }
     },
-    [dispatch, selectedMembers, showSuggestions]
+    [selectedMembers]
   );
 
   const onUpdate = useCallback(
@@ -170,10 +177,8 @@ const AddModal = ({ open, onClose, teamId, validateAdds, showSuggestions }) => {
       else setValidationError(false);
 
       setResponseErrors([]);
-
-      dispatch(clearSuggestions());
     },
-    [dispatch, validateAdds]
+    [validateAdds]
   );
 
   const addButton = (
@@ -196,15 +201,17 @@ const AddModal = ({ open, onClose, teamId, validateAdds, showSuggestions }) => {
       disabled={loading}
       extraModalStyle={{ overflowY: "visible" }}
     >
-      <ReactSelect
+      <AsyncSelect
         value={selectedMembers}
         onChange={onUpdate}
-        options={options}
+        cacheOptions
         onInputChange={onInputChange}
         isMulti
         placeholder="Enter email address(es) or user handles"
-        isCreatable
         noOptionsText="Type to search"
+        loadingText="Loading..."
+        loadOptions={showSuggestions ? loadSuggestions: emptySuggestions}
+        defaultOptions={[]}
       />
       {validationError && (
         <div styleName="error-message">
diff --git a/src/routes/TeamAccess/reducers/index.js b/src/routes/TeamAccess/reducers/index.js
index 5be42a8f..66b736d5 100644
--- a/src/routes/TeamAccess/reducers/index.js
+++ b/src/routes/TeamAccess/reducers/index.js
@@ -6,7 +6,6 @@ import { ACTION_TYPE } from "constants";
 const initialState = {
   members: undefined,
   invites: undefined,
-  suggestions: [],
   loading: false,
   error: undefined,
   updating: false,
@@ -84,34 +83,6 @@ const reducer = (state = initialState, action) => {
         error: action.payload,
       };
 
-    case ACTION_TYPE.LOAD_MEMBERS_SUGGESTIONS_PENDING:
-      return {
-        ...state,
-        loading: true,
-        error: undefined,
-      };
-
-    case ACTION_TYPE.LOAD_MEMBERS_SUGGESTIONS_SUCCESS:
-      return {
-        ...state,
-        suggestions: action.payload,
-        loading: false,
-        error: undefined,
-      };
-
-    case ACTION_TYPE.LOAD_MEMBERS_SUGGESTIONS_ERROR:
-      return {
-        ...state,
-        loading: false,
-        error: action.payload,
-      };
-
-    case ACTION_TYPE.CLEAR_MEMBERS_SUGGESTIONS:
-      return {
-        ...state,
-        suggestions: [],
-      };
-
     case ACTION_TYPE.ADD_MEMBERS_PENDING:
       return {
         ...state,