def METHOD_NAME(logger):
    """
    Create new indices for our indexables and replace possible existing indices with
    a new one only once it has successfully built it.
    """
    # Get all existing indices once; we'll look up into this list many times
    try:
        existing_indices = ES_INDICES_CLIENT.get_alias("*")
    except NotFoundError:
        # Provide a fallback empty list so we don't have to check for its existence later on
        existing_indices = []
    # Create a new index for each of those modules
    # NB: we're mapping perform_create_index which produces side-effects
    indices_to_create = zip(
        list(map(lambda ix: perform_create_index(ix, logger), ES_INDICES)), ES_INDICES
    )
    # Prepare to alias them so they can be swapped-in for the previous versions
    actions_to_create_aliases = [
        {"add": {"index": index, "alias": ix.index_name}}
        for index, ix in indices_to_create
    ]
    # Get the previous indices for every alias
    indices_to_unalias = reduce(
        lambda acc, ix: acc
        + list(get_indices_by_alias(existing_indices, ix.index_name)),
        ES_INDICES,
        [],
    )
    # Prepare to un-alias them so they can be swapped-out for the new versions
    # NB: use chain to flatten the list of generators
    actions_to_delete_aliases = [
        {"remove": {"index": index, "alias": alias}}
        for index, alias in indices_to_unalias
    ]
    # Identify orphaned indices that belong to our own app.
    # NB: we *must* do this before the update_aliases call so we don't immediately prune
    # version n-1 of all our indices
    useless_indices = [
        index
        for index, details in existing_indices.items()
        if index.startswith(str(ES_INDICES_PREFIX)) and not details["aliases"]
    ]
    # Replace the old indices with the new ones in 1 atomic operation to avoid outage
    def perform_aliases_update():
        try:
            ES_INDICES_CLIENT.update_aliases(
                {"actions": actions_to_create_aliases + actions_to_delete_aliases}
            )
        except RequestError as exception:
            # This operation can fail if an index exists with the same name as an alias we're
            # attempting to create. In Richie, this is not supposed to happen and is usually the
            # result of a broken ES state.
            if exception.error == "invalid_alias_name_exception":
                try:
                    # ES6 provides the name of the broken index directly
                    broken_index = exception.info["error"]["index"]
                except KeyError:
                    # With ES7 we have to extract the name of the broken index from a string
                    pattern = re.compile(r"Invalid alias name \[(.*)\].*")
                    broken_index = pattern.match(
                        exception.info["error"]["reason"]
                    ).group(1)
                # Delete it (it was unusable and we can recreate its data at-will)
                ES_INDICES_CLIENT.delete(index=broken_index)
                # Attempt to perform the operation again
                # We're doing this recursively in case more than one such broken indices existed
                # (eg. "richie_courses" and "richie_organizations")
                perform_aliases_update()
            # Let other kinds of errors be raised
            else:
                raise exception
    perform_aliases_update()
    for useless_index in useless_indices:
        # Disable keyword arguments checking as elasticsearch-py uses a decorator to list
        # valid query parameters and inject them as kwargs. I won't say a word about this
        # anti-pattern.
        #
        # pylint: disable=unexpected-keyword-arg
        ES_INDICES_CLIENT.delete(index=useless_index, ignore=[400, 404])