How should I perform a redirect in hook_form_alter()? When users log in, I want to redirect them to another page, when they have a certain role. In Drupal 7, I'd use drupal_goto() in hook_user_login() to do the redirect, and hook_module_implements_alter() to make sure that my module is last in the list, so that everything else gets a chance to run.

In Drupal 8, it seems that performing a redirect outside of a controller is not a supported use case.

On that page, gngn has the same problem, and manually generates a RedirectResponse and sends it.

The problem is that, as I see it, send() doesn't terminate the request and the page will have two HTML documents: a 'redirecting to...' page, followed by whatever page would have been there in the first place. Which could be a security issue.

johnvb notes this, and inserts a call to exit() after send().

Presumably something useful is being done in the $kernel-&gt;terminate() call in index.php, which is being bypassed by calling exit().

In Drupal 7, drupal_goto() called drupal_exit() to handle this problem. 

drupal_goto() was removed says that modules needing to interrupt the request flow should throw an HTTP exception, but there are no 'redirect' exceptions.

As the user login also does a redirect, another approach would be to alter the redirection URL, as suggested on the drupal_goto() change record link above. However, that approach will result in my method being called on every single request, which for what I'm doing seems insanely wasteful.

So, how should I perform a redirect from hook_form_alter() in Drupal 8?
use Drupal\Core\Form\FormStateInterface;

/** 
 * Implements hook_form_FORM_ID_alter().
 */
function [MODULENAME]_form_user_login_form_alter(&amp;$form, FormStateInterface $form_state, $form_id) {
  // Alter login form and add own custom submit handler.
  $form['#submit'][] = '_[MODULENAME]_user_login_form_submit';

  // Not all forms pay attention to $form['#submit'][]. For these
  // try adding your submit hook to the #submit for the specific
  // button.  e.g.,
  $form['actions']['submit']['#submit'][] = '_[MODULENAME]_user_login_form_submit';
}

/**
 * Custom submit handler for login form.
 */
function _[MODULENAME]_user_login_form_submit($form, FormStateInterface $form_state) {
  // Set redirect to login form.
  $form_state-&gt;setRedirect('custom.redirect_callback');
}