diff --git a/drupalorg/drupalorg.module b/drupalorg/drupalorg.module
index 1ae939b4c18d328d3575b1e7a41ddfcc45327c06..38c8585f429126aa1dc9dd0cf7085e1b852194be 100644
--- a/drupalorg/drupalorg.module
+++ b/drupalorg/drupalorg.module
@@ -400,6 +400,13 @@ function drupalorg_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'drupalorg.pages.inc',
   ];
+  $items['drupalorg-keycloak-event/%/%'] = [
+    'access callback' => 'drupalorg_keycloak_relay_event_access',
+    'page callback' => 'drupalorg_keycloak_event',
+    'page arguments' => [1, 2],
+    'type' => MENU_CALLBACK,
+    'file' => 'drupalorg.pages.inc',
+  ];
 
   // Queue in-place-update “quasi diff” generation.
   $items['in-place-updates/%project/%drupalorg_in_place_update'] = [
@@ -665,6 +672,22 @@ function drupalorg_gitlab_webhook_access() {
   return TRUE;
 }
 
+/**
+ * Menu access callback, validate Keycloak event payload.
+ */
+function drupalorg_keycloak_relay_event_access() {
+  if (empty(variable_get('drupalorg_keycloak_event_token'))) {
+    return FALSE;
+  }
+  if (empty($_SERVER['HTTP_X_KEYCLOAK_TOKEN'])) {
+    return FALSE;
+  }
+  if ($_SERVER['HTTP_X_KEYCLOAK_TOKEN'] !== variable_get('drupalorg_keycloak_event_token')) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
 /**
  * Menu title callback. Be more welcoming than core.
  */
@@ -6471,6 +6494,10 @@ function drupalorg_cron_queue_info() {
       'worker callback' => 'drupalorg_keycloak_process',
       'skip on cron' => TRUE,
     ],
+    'drupalorg_keycloak_event' => [
+      'worker callback' => 'drupalorg_keycloak_event_process',
+      'skip on cron' => TRUE,
+    ],
     'drupalorg_commits_comments' => [
       'worker callback' => 'drupalorg_commits_comments_process',
       'skip on cron' => TRUE,
@@ -11095,3 +11122,42 @@ function drupalorg_get_gitlab_project_id($namespace, $name) {
 
   return $ids[$key];
 }
+
+/**
+ * Queue worker callback for KC delete account event.
+ *
+ * @param array $item
+ *   The queue item. An map with the following keys.
+ *   - 'uid': Drupal user id.
+ *   - 'keycloak_uuid': Keycloak user UUID.
+ */
+function drupalorg_keycloak_event_process($item) {
+  if (empty($item['keycloak_uuid']) || empty($item['uid'] || empty($item['event']))) {
+    watchdog('drupalorg_keycloak_event', 'Incomplete item on the queue: @item', [
+      '@item' => print_r($item, 1),
+    ], WATCHDOG_ERROR);
+    return;
+  }
+  $keycloak_user = (new KeycloakIntegration())->getUser($item['keycloak_uuid']);
+
+  switch ($item['event']) {
+    case 'delete':
+      if (!is_null($keycloak_user)) {
+        watchdog('drupalorg_keycloak_event', 'Keycloak user still exists, skip deleting it: @item', [
+          '@item' => print_r($item, 1),
+        ], WATCHDOG_ERROR);
+        return;
+      }
+      watchdog('drupalorg_keycloak_events_user_delete_process', 'Deleting drupal user uid "@uid" following a Keycloak user uuid "@uuid" delete', [
+        '@uid' => $item['uid'],
+        '@uuid' => $item['keycloak_uuid'],
+      ], WATCHDOG_INFO);
+      user_delete($item['uid']);
+      return;
+
+    default:
+      watchdog('drupalorg_keycloak_event', 'Unrecognised event on item: @item', [
+        '@item' => print_r($item, 1),
+      ], WATCHDOG_ERROR);
+  }
+}
diff --git a/drupalorg/drupalorg.pages.inc b/drupalorg/drupalorg.pages.inc
index eea6aabee6cbb08254cb6b42a2331fd691f2fd34..e1bb19dfcaffc615531c1be7968633536638386f 100644
--- a/drupalorg/drupalorg.pages.inc
+++ b/drupalorg/drupalorg.pages.inc
@@ -1662,3 +1662,98 @@ function drupalorg_registration_validation_text_form_submit($form, &$form_state)
 
   drupal_set_message(t('Support request emailed to <a href="mailto:help@drupal.org">help@drupal.org</a>.'));
 }
+
+/**
+ * Menu callback, handle Keycloak relayed event.
+ *
+ * @param string $event_trigger
+ *   Trigger that produced the event.
+ *   Either 'user' or 'admin'.
+ * @param string $event_type
+ *   Type of sent on the payload.
+ *
+ * Payload is JSON with the event data.
+ * E.g.
+ * @code
+ * {
+ *   "event_trigger": "user",
+ *   "event": {
+ *     "id": "0c9061c8-8656-4b73-9302-9cf52e94922b",
+ *     "time": "1725046809362",
+ *     "type": "CODE_TO_TOKEN",
+ *     "realm_id": "Main",
+ *     "client_id": "account-console",
+ *     "user_id": "80cefc10-1d71-4b5b-b079-39345ab5e65d",
+ *     "session_id": "9ecd59b9-7c17-4fc2-adc6-422f4d2bdace",
+ *     "ip_address": "192.168.1.101",
+ *     "error": ""
+ *   }
+ * }
+ * @endcode
+ */
+function drupalorg_keycloak_event($event_trigger, $event_type) {
+  if (empty($event_trigger) || empty($event_type)) {
+    // Missing arguments.
+    watchdog('drupalorg_keycloak_event', 'Keycloak sent an event with missing arguments, event trigger was "@trigger", and event type was "@type".', [
+      '@trigger' => $event_trigger,
+      '@type' => $event_type,
+    ], WATCHDOG_ERROR);
+    drupal_add_http_header('Status', '400 Bad Request');
+    print '{"error": "Empty event trigger or event type in request path"}';
+    drupal_page_footer();
+    exit();
+  }
+  if ($event_trigger !== 'user') {
+    // Only support KC user events for now.
+    drupal_add_http_header('Status', '204 No Content');
+    drupal_page_footer();
+    exit();
+  }
+  $user_event = json_decode(file_get_contents('php://input'), true);
+  switch ($event_type) {
+    case 'DELETE_ACCOUNT':
+      _drupalorg_keycloak_event_handle_delete_account($user_event);
+      break;
+    default:
+      // Unsupported event type.
+      drupal_add_http_header('Status', '204 No Content');
+  }
+  drupal_add_http_header('Content-Type', 'text/plain');
+  echo '👋';
+  drupal_page_footer();
+  exit();
+}
+
+/**
+ * Handles KC user delete event.
+ *
+ * @param array $user_event
+ *   Parsed JSON payload on POST. See payload example on
+ *   drupalorg_keycloak_event().
+ */
+function _drupalorg_keycloak_event_handle_delete_account($user_event) {
+  if (empty($user_event['event']['user_id'])) {
+    // Cannot continue without a Keycloak UUID.
+    watchdog('drupalorg_keycloak_event', 'Keycloak sent a user event without event.user_id set: @payload', [
+      '@payload' => print_r($user_event, 1),
+    ], WATCHDOG_ERROR);
+    return;
+  }
+  $event = $user_event['event'];
+  $uid = db_query("SELECT uid FROM {authmap} WHERE module = 'openid_connect_keycloak' AND authname = :authname", [
+    ':authname' => $event['user_id'],
+  ])->fetchField();
+  if (empty($uid)) {
+    // Cannot find a related user id.
+    watchdog('drupalorg_keycloak_event', 'Provided Keycloak UUID "@uuid" does not have a related entry on authmap: @payload', [
+      '@uuid' => print_r($event['user_id'], TRUE),
+      '@payload' => print_r($event, TRUE),
+    ], WATCHDOG_ERROR);
+    return;
+  }
+  DrupalQueue::get('drupalorg_keycloak_event')->createItem([
+    'uid' => $uid,
+    'keycloak_uuid' => $event['user_id'],
+    'event' => 'delete',
+  ]);
+}