diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py
index c764bfe8c21b5dfa7dc7657124d5e6fabfef5710..5dd620056094ed294035c5ad86cbc0084e8fe922 100644
--- a/homeassistant/bootstrap.py
+++ b/homeassistant/bootstrap.py
@@ -18,6 +18,7 @@ from homeassistant.util.logging import AsyncHandler
 from homeassistant.util.package import async_get_user_site, is_virtual_env
 from homeassistant.util.yaml import clear_secret_cache
 from homeassistant.exceptions import HomeAssistantError
+from homeassistant.helpers import config_validation as cv
 
 _LOGGER = logging.getLogger(__name__)
 
@@ -153,6 +154,34 @@ async def async_from_config_dict(config: Dict[str, Any],
     stop = time()
     _LOGGER.info("Home Assistant initialized in %.2fs", stop-start)
 
+    # TEMP: warn users for invalid slugs
+    # Remove after 0.94 or 1.0
+    if cv.INVALID_SLUGS_FOUND or cv.INVALID_ENTITY_IDS_FOUND:
+        msg = []
+
+        if cv.INVALID_ENTITY_IDS_FOUND:
+            msg.append(
+                "Your configuration contains invalid entity ID references. "
+                "Please find and update the following. "
+                "This will become a breaking change."
+            )
+            msg.append('\n'.join('- {} -> {}'.format(*item)
+                                 for item
+                                 in cv.INVALID_ENTITY_IDS_FOUND.items()))
+
+        if cv.INVALID_SLUGS_FOUND:
+            msg.append(
+                "Your configuration contains invalid slugs. "
+                "Please find and update the following. "
+                "This will become a breaking change."
+            )
+            msg.append('\n'.join('- {} -> {}'.format(*item)
+                                 for item in cv.INVALID_SLUGS_FOUND.items()))
+
+        hass.components.persistent_notification.async_create(
+            '\n\n'.join(msg), "Config Warning", "config_warning"
+        )
+
     return hass
 
 
diff --git a/homeassistant/helpers/config_validation.py b/homeassistant/helpers/config_validation.py
index 475135b4cced6a78f5794bd5e256f85531d25550..1edf52cbb7fee92fad4591edd03b873702f437bd 100644
--- a/homeassistant/helpers/config_validation.py
+++ b/homeassistant/helpers/config_validation.py
@@ -26,6 +26,13 @@ from homeassistant.helpers import template as template_helper
 # pylint: disable=invalid-name
 
 TIME_PERIOD_ERROR = "offset {} should be format 'HH:MM' or 'HH:MM:SS'"
+OLD_SLUG_VALIDATION = r'^[a-z0-9_]+$'
+OLD_ENTITY_ID_VALIDATION = r"^(\w+)\.(\w+)$"
+# Keep track of invalid slugs and entity ids found so we can create a
+# persistent notification. Rare temporary exception to use a global.
+INVALID_SLUGS_FOUND = {}
+INVALID_ENTITY_IDS_FOUND = {}
+
 
 # Home Assistant types
 byte = vol.All(vol.Coerce(int), vol.Range(min=0, max=255))
@@ -149,6 +156,18 @@ def entity_id(value: Any) -> str:
     value = string(value).lower()
     if valid_entity_id(value):
         return value
+    elif re.match(OLD_ENTITY_ID_VALIDATION, value):
+        # To ease the breaking change, we allow old slugs for now
+        # Remove after 0.94 or 1.0
+        fixed = '.'.join(util_slugify(part) for part in value.split('.', 1))
+        INVALID_ENTITY_IDS_FOUND[value] = fixed
+        logging.getLogger(__name__).warning(
+            "Found invalid entity_id %s, please update with %s. This "
+            "will become a breaking change.",
+            value, fixed
+        )
+        return value
+
     raise vol.Invalid('Entity ID {} is an invalid entity id'.format(value))
 
 
@@ -333,7 +352,22 @@ def schema_with_slug_keys(value_schema: Union[T, Callable]) -> Callable:
             raise vol.Invalid('expected dictionary')
 
         for key in value.keys():
-            slug(key)
+            try:
+                slug(key)
+            except vol.Invalid:
+                # To ease the breaking change, we allow old slugs for now
+                # Remove after 0.94 or 1.0
+                if re.match(OLD_SLUG_VALIDATION, key):
+                    fixed = util_slugify(key)
+                    INVALID_SLUGS_FOUND[key] = fixed
+                    logging.getLogger(__name__).warning(
+                        "Found invalid slug %s, please update with %s. This "
+                        "will be come a breaking change.",
+                        key, fixed
+                    )
+                else:
+                    raise
+
         return schema(value)
     return verify
 
diff --git a/tests/helpers/test_config_validation.py b/tests/helpers/test_config_validation.py
index 03dd3cfe55a5e5124494d5bc293a7fe6def2da4b..1bae84b532080c38d4c77cd9951c6aaa2193381f 100644
--- a/tests/helpers/test_config_validation.py
+++ b/tests/helpers/test_config_validation.py
@@ -602,3 +602,31 @@ def test_comp_entity_ids():
     for invalid in (['light.kitchen', 'not-entity-id'], '*', ''):
         with pytest.raises(vol.Invalid):
             schema(invalid)
+
+
+def test_schema_with_slug_keys_allows_old_slugs(caplog):
+    """Test schema with slug keys allowing old slugs."""
+    schema = cv.schema_with_slug_keys(str)
+
+    with patch.dict(cv.INVALID_SLUGS_FOUND, clear=True):
+        for value in ('_world', 'wow__yeah'):
+            caplog.clear()
+            # Will raise if not allowing old slugs
+            schema({value: 'yo'})
+            assert "Found invalid slug {}".format(value) in caplog.text
+
+        assert len(cv.INVALID_SLUGS_FOUND) == 2
+
+
+def test_entity_id_allow_old_validation(caplog):
+    """Test schema allowing old entity_ids."""
+    schema = vol.Schema(cv.entity_id)
+
+    with patch.dict(cv.INVALID_ENTITY_IDS_FOUND, clear=True):
+        for value in ('hello.__world', 'great.wow__yeah'):
+            caplog.clear()
+            # Will raise if not allowing old entity ID
+            schema(value)
+            assert "Found invalid entity_id {}".format(value) in caplog.text
+
+        assert len(cv.INVALID_ENTITY_IDS_FOUND) == 2