DEV Community

Edgardo Genini
Edgardo Genini

Posted on

[ES] Delegated Resource Identifier (DRI): un patrón para referencias persistentes en microservicios

También disponible en Inglés

Si alguna vez guardaste una URL en una base de datos y después te arrepentiste, esto es para vos.

Es un escenario conocido: un servicio necesita mantener una referencia a un recurso que vive en otro servicio. La solución más obvia es guardar la URL. Funciona, hasta que el host cambia, la API sube de versión, o el equipo decide reestructurar los paths. De repente todas las referencias guardadas están rotas, y rastrear el impacto se convierte en un problema mayor de lo que debería ser.

El problema de fondo es que una URL mezcla dos cosas distintas: qué es el recurso y dónde está. Cuando guardás una URL estás apostando a que esa ubicación no va a cambiar. En sistemas que evolucionan, esa apuesta suele perderse.

La idea

¿Qué pasaría si en lugar de guardar dónde está el recurso, guardás un identificador propio que un gateway sabe cómo resolver?

comercio:pedidos/orden:id=ARG-2024-00091872
finanzas:cuentas/cliente:estado:id=109234
salud:cobertura/credencial:patient-id=12345678
Enter fullscreen mode Exit fullscreen mode

Quien guarda la referencia no necesita saber dónde vive el recurso ni cómo se accede. Esa responsabilidad la tiene el gateway. Si la API cambia, si el servicio migra, si aparece un sistema nuevo: solo cambia el resolver. Las referencias guardadas siguen siendo válidas.

A este esquema lo llamé Delegated Resource Identifier (DRI).

Lo que este patrón no es

  • No es un estándar
  • Requiere un gateway como intermediario: no aplica cuando el cliente necesita acceder directamente al recurso sin pasar por ningún intermediario
  • No impone una taxonomía de contextos: cada equipo define la suya

Es una convención útil cuando necesitás referencias persistentes a recursos en un ecosistema controlado, y querés centralizar la lógica de resolución.

Cómo se construye

El identificador tiene dos partes separadas por /:

<contexto>/<recurso>
Enter fullscreen mode Exit fullscreen mode
  • Contexto (lado izquierdo): identifica el dominio que sabe resolver este tipo de recurso. El gateway lo usa para rutear.
  • Recurso (lado derecho): identifica el recurso concreto. Su estructura la define quien implementa el resolver.
comercio:pedidos/orden:id=ARG-2024-00091872
└─── ruteo ──────┘└─── recurso concreto ──┘
Enter fullscreen mode Exit fullscreen mode

Los : separan niveles jerárquicos. El = asigna valores. Cada lado define su propia convención interna.

El identificador lo construye quien guarda la referencia, a partir del dato que ya tiene y el contexto que conoce. No requiere ninguna llamada externa. Un servicio de facturación que recibe el ID de una orden sabe que pertenece a comercio:pedidos y construye el DRI al momento de persistir la referencia.

El contexto puede omitirse si el gateway tiene un resolver por defecto:

/orden:id=ARG-2024-00091872
Enter fullscreen mode Exit fullscreen mode

Algunos casos de uso

E-commerce: recuperar una orden

Un servicio de atención al cliente guarda referencias a órdenes que pueden venir de distintos canales: tienda propia, marketplace, app móvil. Cada canal tiene su propia API.

comercio:pedidos/orden:id=ARG-2024-00091872
comercio:pedidos/orden:id=MKT-2024-00034521
Enter fullscreen mode Exit fullscreen mode

El resolver de comercio:pedidos determina a qué canal pertenece cada orden a partir del prefijo del ID y rutea hacia la API correspondiente. El identificador es estable aunque la API del canal cambie.

Fintech: estado de cuenta de un cliente

Un banco con sistemas legacy y modernos conviviendo. El resolver determina en qué sistema vive el cliente según el valor del ID: clientes con id < 50000 en el sistema legacy, el resto en el moderno.

finanzas:cuentas/cliente:estado:id=109234
finanzas:cuentas/cliente:estado:id=002871
Enter fullscreen mode Exit fullscreen mode

El resolver encapsula también la decisión de qué versión de la API usar. Y acá aparece algo interesante: el DRI tiene dos momentos de vida. Cuando se persiste es solo el identificador. Cuando se usa para consultar, puede enriquecerse con contexto adicional usando la misma sintaxis:

finanzas:cuentas/cliente:estado:id=109234:fecha=20260101
Enter fullscreen mode Exit fullscreen mode

El resolver puede usar esa fecha para determinar qué versión de la API corresponde. El DRI persistido no cambia; el contexto adicional se agrega en el momento de la consulta.

Salud: credencial de cobertura de un afiliado

La cobertura de un afiliado puede cambiar en el tiempo: migración de proveedor, períodos sin cobertura, cobertura en más de uno. Guardar el proveedor como dato fijo generaría referencias desactualizadas.

salud:cobertura/credencial:patient-id=12345678
Enter fullscreen mode Exit fullscreen mode

El resolver aplica una estrategia de fallback: consulta al primer proveedor disponible y si no encuentra la credencial prueba con el siguiente. El DRI resuelve en el momento de la consulta, reflejando siempre el estado actual.

Multinacional con tenant: proveedor por entidad legal

Una plataforma SaaS con operaciones en múltiples países. Cada país tiene su propio sistema, su propia API y su propio formato de identificador fiscal.

tenant:acme:ar/proveedor:cuit=20123456789
tenant:acme:cl/proveedor:rut=76354921-5
tenant:acme:mx/proveedor:rfc=XYZ123456789
Enter fullscreen mode Exit fullscreen mode

El lado izquierdo combina tenant y entidad legal por país. El lado derecho respeta la convención local. Agregar una nueva filial o un nuevo tenant es registrar un resolver adicional, sin tocar las referencias existentes. La jerarquía del contexto crece naturalmente con el sistema.

Cómo funciona el gateway

El flujo de resolución es simple: el gateway recibe el identificador, extrae el contexto y delega al resolver correspondiente.

cliente  →  gateway  →  resolver(comercio:pedidos)  →  servicio real
Enter fullscreen mode Exit fullscreen mode
  1. Recibe el identificador
  2. Extrae el contexto (lado izquierdo)
  3. Delega al resolver registrado para ese contexto
  4. El resolver obtiene el recurso y devuelve la respuesta

El gateway no conoce recursos concretos. A modo de referencia orientativa, una posible implementación en Java:

gateway.register("comercio:pedidos", new OrderResolver());
gateway.register("finanzas:cuentas", new AccountResolver());
gateway.register("salud:cobertura",  new CoverageResolver());
Enter fullscreen mode Exit fullscreen mode
public interface ResourceResolver {
    Response resolve(ResourceIdentifier identifier);
}
Enter fullscreen mode Exit fullscreen mode

Preferencias opcionales

El identificador admite expresar preferencias sobre cómo debe resolverse el recurso, con una sintaxis inspirada en el header Accept de HTTP. Por ejemplo, al consultar medios de pago se puede indicar preferencia por débito sobre crédito:

pagos:medios/disponibles:cliente:id=109234;debito,q=0.9;credito,q=0.7
Enter fullscreen mode Exit fullscreen mode

El significado de q lo define el contrato entre quien construye la referencia y quien la resuelve. El gateway no necesita interpretarlo. Esta capacidad es completamente opcional.


Lo implementé en Java y me resultó útil en la práctica. Si lo probás en tu contexto o tenés ideas para mejorarlo, me interesa leerlo en los comentarios.

Top comments (0)