diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
new file mode 100644
index 00000000..b976f514
--- /dev/null
+++ b/app/controllers/registrations_controller.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+# Modificaciones locales al registro de usuaries
+#
+# @see {https://github.com/heartcombo/devise/wiki/How-To:-Use-Recaptcha-with-Devise}
+class RegistrationsController < Devise::RegistrationsController
+  class SpambotError < StandardError; end
+
+  PRIVATE_HEADERS = /(cookie|secret|token)/i
+
+  prepend_before_action :anti_spambot_traps, only: %i[create]
+  prepend_after_action :lock_spambots, only: %i[create]
+
+  private
+
+  # Condiciones bajo las que consideramos que un registro viene de unx
+  # spambot
+  #
+  # @return [Bool]
+  def spambot?
+    @spambot ||= params.dig(:usuarie, :name).present?
+  end
+
+  # Bloquea las cuentas de spam dentro de un minuto, para hacerles creer
+  # que la cuenta se creó correctamente.
+  def lock_spambots
+    return unless spambot?
+    return unless current_usuarie
+
+    LockUsuarieJob.set(wait: 1.minute).perform_later(usuarie: current_usuarie)
+  end
+
+  # Detecta e informa spambots muy simples
+  #
+  # @return [nil]
+  def anti_spambot_traps
+    raise SpambotError if spambot?
+  rescue SpambotError => e
+    ExceptionNotifier.notify_exception(e, data: { params: anonymized_params, headers: anonymized_headers })
+    nil
+  end
+
+  # Devuelve parámetros anonimizados para prevenir filtrar la contraseña
+  # de falsos positivos.
+  #
+  # @return [Hash]
+  def anonymized_params
+    params.except(:authenticity_token).permit!.to_h.tap do |p|
+      p['usuarie'].delete 'password'
+      p['usuarie'].delete 'password_confirmation'
+    end
+  end
+
+  # Devuelve los encabezados de la petición sin información sensible de
+  # Rails
+  #
+  # @return [Hash]
+  def anonymized_headers
+    request.headers.to_h.select do |_, v|
+      v.is_a? String
+    end.reject do |k, _|
+      k =~ PRIVATE_HEADERS
+    end
+  end
+
+  # Si le usuarie es considerade spambot, no enviamos el correo de
+  # confirmación al crear la cuenta.
+  def sign_up_params
+    if spambot?
+      params[:usuarie][:confirmed_at] = Time.now.utc
+
+      devise_parameter_sanitizer.permit(:sign_up, keys: %i[confirmed_at])
+    end
+
+    super
+  end
+end
diff --git a/app/jobs/lock_usuarie_job.rb b/app/jobs/lock_usuarie_job.rb
new file mode 100644
index 00000000..8af6ee83
--- /dev/null
+++ b/app/jobs/lock_usuarie_job.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# Bloquea el acceso a une usuarie
+class LockUsuarieJob < ApplicationJob
+  # Cambiamos la contraseña, aplicamos un bloqueo y cerramos la sesión
+  # para que no pueda volver a entrar hasta que siga las instrucciones
+  # de desbloqueo.
+  #
+  # @param :usuarie [Usuarie]
+  # @return [nil]
+  def perform(usuarie:)
+    password = SecureRandom.base36
+
+    usuarie.skip_password_change_notification!
+    usuarie.update(password: password, password_confirmation: password, remember_created_at: nil, locked_at: Time.now.utc)
+
+    nil
+  end
+end
diff --git a/app/views/devise/registrations/new.haml b/app/views/devise/registrations/new.haml
index aabc0487..4c562fc3 100644
--- a/app/views/devise/registrations/new.haml
+++ b/app/views/devise/registrations/new.haml
@@ -12,6 +12,9 @@
       as: resource_name,
       url: registration_path(resource_name, params: { locale: params[:locale] })) do |f|
 
+      .d-none
+        = f.text_field :name, autocomplete: 'off'
+
       .form-group
         = f.label :email, class: 'sr-only'
         = f.email_field :email, autofocus: true, autocomplete: 'email',
diff --git a/config/routes.rb b/config/routes.rb
index 3dfc4c85..1123f9ee 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -6,7 +6,7 @@
 SITE_ID_RE = %r{[^/]+}.freeze
 
 Rails.application.routes.draw do
-  devise_for :usuaries
+  devise_for :usuaries, controllers: { registrations: 'registrations' }
   get '/.well-known/change-password', to: redirect('/usuaries/edit')
 
   require 'que/web'