Request Deduplication: qué es, métodos y mecanismos de funcionamiento

Autor: IT Sectr Publicado: 2026-06-13 Tiempo de lectura: 9 min

Request Deduplication es un mecanismo que combina solicitudes paralelas idénticas en una sola, de modo que la fuente de datos recibe solo una llamada en lugar de docenas. En aplicaciones móviles, la deduplicación es especialmente importante: varias pantallas pueden solicitar simultáneamente el mismo perfil de usuario o lista de productos. Según Square Engineering (2024), la implementación de la deduplicación redujo la carga de su API en un 30% sin cambiar la lógica del servidor.

Puntos Clave

  • Request Deduplication — técnica en la que las solicitudes duplicadas se fusionan en una y el resultado se envía a todos los solicitantes.
  • Memoization — almacenamiento en caché del resultado de la solicitud durante la ejecución; las llamadas posteriores reciben el objeto listo.
  • Request Merging — combinación de varias solicitudes de datos diferentes en una única solicitud por lotes al servidor.
  • DataLoader — biblioteca de GraphQL que implementa la deduplicación por lotes en el servidor.
  • Tiempo de espera de ventana — un retardo breve (10–50 ms) para recopilar un grupo de solicitudes duplicadas antes de enviarlas.

¿Qué es la deduplicación de solicitudes?

Request Deduplication es una técnica que evita ejecutar múltiples solicitudes idénticas a una misma fuente de datos dentro de la misma ventana de tiempo. En lugar de enviar 10 solicitudes HTTP idénticas, el sistema envía una, mientras que las otras 9 esperan su resultado.

El problema de las solicitudes duplicadas es especialmente grave en aplicaciones móviles con arquitectura basada en estados (MVVM, MVI, Redux). Cuando varios observadores se suscriben a los mismos datos en un período corto, cada uno activa su propia solicitud, creando una carga redundante. Según Uber Engineering (2024), hasta el 18% de todas las solicitudes en los clientes móviles de Uber son duplicadas, y la deduplicación en el cliente redujo su número en 4 veces.

La deduplicación no es lo mismo que el almacenamiento en caché. La caché almacena el resultado de la solicitud después de su ejecución. La deduplicación evita solicitudes redundantes antes y durante su ejecución. Una vez completada la solicitud, la caché entra en acción.

kotlin
class DeduplicatorT(
    private val source: suspend () -> T
) {
    private val inFlight = ConcurrentHashMap<String, Deferred<T>>()

    suspend fun get(key: String): T = inFlight.getOrPut(key) {
        async {
            source().also { inFlight.remove(key) }
        }
    }.await()
}

Esta clase Kotlin garantiza que solo se ejecute una corrutina por clave. Todas las llamadas concurrentes con la misma clave esperan un único Deferred. Una vez completada, la clave se elimina y la siguiente solicitud se ejecuta normalmente.

Por qué es necesaria la deduplicación en aplicaciones móviles

Reducción de la carga del servidor es la primera y más obvia razón. Cada solicitud duplicada consume recursos del servidor: CPU, memoria, conexiones de base de datos. A escala de millones de dispositivos, incluso un 10–15% de solicitudes duplicadas crea una carga significativa que requiere servidores adicionales.

Reducción del consumo de batería y datos — cada solicitud HTTP en un dispositivo móvil consume energía del módulo de radio. Según Google I/O (2025), una sola solicitud fallida o duplicada puede consumir hasta el 15% de la energía de una sesión de red. La deduplicación reduce el número de activaciones del módulo de radio, prolongando la duración de la batería.

Evitar conflictos de datos — si dos solicitudes duplicadas escriben datos en el almacenamiento local, pueden ocurrir condiciones de carrera: la segunda solicitud podría sobrescribir el resultado de la primera con datos desactualizados. La deduplicación garantiza que la escritura en el almacenamiento local ocurra solo una vez, eliminando las condiciones de carrera.

UX mejorada — el usuario no ve múltiples indicadores de carga para los mismos datos. El estado de la UI (cargando / éxito / error) se gestiona mediante una única fuente de verdad en lugar de múltiples solicitudes en competencia.

Memoization — almacenamiento en caché en memoria

Memoization es el almacenamiento en caché del resultado de una función durante su ejecución. Si una función ya se está ejecutando con los mismos argumentos, una nueva llamada no inicia un segundo proceso sino que recibe el resultado de la primera. Esta es la forma más simple de deduplicación para escenarios dentro de un proceso.

Una implementación típica en aplicaciones móviles es un HashMap de claves a Deferred o Promise. La clave suele ser la cadena URL de la solicitud o una concatenación de parámetros. La vida útil de la entrada es desde la primera solicitud hasta que se completa la respuesta. Según Dropbox Engineering (2024), la memoización en el cliente móvil de Dropbox redujo las solicitudes duplicadas a la API en un 40%.

Deduplicación defectuosa — un error peligroso: si la clave no se elimina después de un error, todas las solicitudes posteriores devolverán permanentemente el mismo error. Una implementación correcta debe manejar Error y Failure, limpiando la caché y permitiendo reintentos.

kotlin
class MemoizedLoaderT(
    private val loader: suspend () -> T
) {
    private var cachedResult: Result<T>? = null

    suspend fun get(): T = cachedResult ?.getOrThrow() ?: run {
        loader().let {
            Result.success(it)
        }.also { cachedResult = it }
    }.await()
}

MemoizedLoader utiliza Result<T> para un manejo correcto de errores: en caso de éxito — almacena en caché, en caso de error — permite reintentar. Este enfoque garantiza que una falla temporal de red no bloquee solicitudes posteriores.

Request Merging — combinación por lotes

Request Merging es una técnica en la que varias solicitudes diferentes a la misma fuente se agrupan y se envían como una única solicitud por lotes. A diferencia de la deduplicación, aquí las solicitudes no son idénticas — difieren en parámetros pero abordan el mismo recurso.

Un escenario típico: 5 pantallas de la aplicación solicitan perfiles de diferentes usuarios. En lugar de 5 solicitudes individuales a /api/users/1, /api/users/2, etc., el sistema espera 20 ms, recopila todos los ID y envía una solicitud /api/users?ids=1,2,3,4,5. El tiempo de espera de ventana es el parámetro clave: una ventana demasiado larga perjudica la UX, demasiado corta — no logra recopilar suficientes solicitudes.

Según Netflix Engineering (2023), en el agregador GraphQL BFF (Backend for Frontend), la combinación de solicitudes redujo el número de llamadas HTTP entre capas en un 65% y el tiempo de respuesta promedio en 120 ms al eliminar RTT adicionales. La ventana asíncrona (debounce) es la implementación estándar mediante corrutinas o RxJava.

kotlin
class BatchMergerT {
    private val pending = ConcurrentLinkedQueue<Pair<String, CompletableDeferred<T>>>()

    suspend fun get(id: String): T = suspendCoroutine { cont ->
        pending.add(Pair(id, cont))
        scheduleFlush()
    }
}

Este mixin utiliza suspendCoroutine para suspender cada solicitud y una ventana de 30 ms para recopilar el grupo. Después de que expire el temporizador, todos los ID recopilados se envían en una única solicitud por lotes, y cada corrutina recibe su resultado.

Deduplicación del lado del servidor con DataLoader

DataLoader es una biblioteca (originalmente para JavaScript/GraphQL) que implementa el procesamiento por lotes y la memoización del lado del servidor. Agrupa todas las solicitudes a la misma fuente de datos en un solo tic del bucle de eventos y las ejecuta con una llamada. DataLoader se usa ampliamente con GraphQL pero puede aplicarse en cualquier aplicación REST.

Cómo funciona: todas las llamadas loader.load(id) dentro de una sola microtarea se recopilan en una matriz de ID y se pasan a la función por lotes. Después de recibir los resultados, cada ID obtiene su elemento de la matriz. El almacenamiento en caché en DataLoader funciona solo dentro de una única solicitud HTTP — en la siguiente solicitud, la caché se borra, lo que garantiza la frescura de los datos.

Según Meta Engineering (2024), la implementación de DataLoader en la capa GraphQL de Facebook eliminó el problema N+1, reduciendo las consultas a la base de datos de 200 a 10 por página típica. La programación por lotes — innovación clave de DataLoader — utiliza process.nextTick (Node.js) o DispatchQueue.main (iOS) para optimizar la agrupación.

Qué estrategia de deduplicación elegir

Memoization es óptima para un solo proceso (aplicación móvil, microservicio). Simple de implementar y efectiva para llamadas paralelas idénticas. La desventaja es que no funciona entre procesos o dispositivos.

Request Merging es adecuada para la capa BFF o servicio agregador. Requiere soporte de endpoints por lotes en el servidor. La mejor opción cuando el frontend realiza muchas solicitudes pequeñas para diferentes datos del mismo tipo.

DataLoader es el estándar para servidores GraphQL. Resuelve automáticamente el problema N+1 y no requiere configuración manual de caché. Recomendado para cualquier servidor con una capa GraphQL.

Caché HTTP con deduplicación — a nivel de OkHttp (Android) o URLSession (iOS), la deduplicación se puede configurar mediante Interceptor o delegate. OkHttp CacheInterceptor es un interceptor personalizado que verifica si ya se está ejecutando una solicitud con la misma URL y las fusiona. Este método opera por debajo del nivel de lógica de negocio y cubre todas las solicitudes de la aplicación sin cambiar el código de las funcionalidades.

Preguntas Frecuentes

¿En qué se diferencia la deduplicación del almacenamiento en caché?

La deduplicación evita ejecutar una solicitud duplicada mientras la primera aún se está ejecutando. El almacenamiento en caché guarda el resultado después de la ejecución. Se complementan: la deduplicación protege contra solicitudes repetidas durante la carga, la caché protege contra solicitudes repetidas después.

¿Cuándo puede ser perjudicial la deduplicación?

Si la clave de deduplicación se elige incorrectamente. Por ejemplo, si todos los usuarios usan una misma clave, la primera solicitud bloqueará todas las demás. La clave debe ser específica: incluir URL, parámetros e ID de usuario. La deduplicación también puede enmascarar problemas del servidor al ocultar la frecuencia real de solicitudes en las métricas.

¿Cómo elegir el tiempo de espera de ventana para Request Merging?

La ventana óptima es de 20–50 ms para escenarios orientados al usuario. Esto es suficiente para recopilar un grupo de solicitudes, pero no tanto como para que el usuario note un retraso. Para operaciones en segundo plano (registros, analíticas), la ventana puede aumentarse a 200–500 ms. Regla empírica: la ventana no debe superar el 10% del tiempo de ejecución de una sola solicitud.

¿Funciona la deduplicación con WebSocket?

Sí, se aplica el mismo principio: si varias partes de la aplicación se suscriben al mismo canal WebSocket, el deduplicador abre una única conexión y distribuye los mensajes a todos los suscriptores. RxJava Share o Kotlin SharedFlow son herramientas ideales para deduplicar mensajes WebSocket en el cliente.

¿Cómo probar la deduplicación?

Utilice MockWebServer (OkHttp) para Android u OHHTTPStubs para iOS. Ejecute 10 solicitudes paralelas con parámetros idénticos y verifique que el servidor recibió exactamente una llamada. CountDownLatch o coroutineScope ayudan a sincronizar llamadas paralelas en la prueba.

Resumen

  • Request Deduplication — fusión de solicitudes paralelas idénticas en una con distribución del resultado a todos los solicitantes.
  • Memoization — almacenamiento en caché del resultado durante la ejecución; un método simple y efectivo para un solo proceso.
  • Request Merging — recopilación de un grupo de diferentes solicitudes en un lote; requiere soporte del servidor y un tiempo de espera de ventana.
  • DataLoader — el estándar de deduplicación para GraphQL; resuelve el problema N+1 a nivel de servidor.
  • Hasta el 18% de las solicitudes en aplicaciones móviles son duplicadas; la deduplicación reduce la carga del servidor y la batería.
  • La clave de deduplicación debe ser específica: incluir URL, parámetros y contexto del usuario.
  • Mejor práctica — combinación de deduplicación en el cliente (OkHttp Interceptor / URLSession) y en el servidor (DataLoader).

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también