Módulo 2: The Bedrock Cost Model

6. Por qué Infracost no puede resolver esto solo, y qué sí puede

Descripción

La lección 5 dejó una pregunta sin respuesta observable: el gate de autenticación de Infracost bloqueó antes de que bedrock.tf se analizara. Esta lección contesta esa pregunta por una vía distinta —no ejecutando scan de nuevo, sino leyendo directamente la documentación pública de qué recursos soporta Infracost— y, con esa respuesta en mano, explica algo más profundo: incluso si Infracost soportara aws_bedrock_guardrail con un precio completo, seguiría sin poder resolver el problema real de costear extract-shipment-manifest-fields. La razón no es un defecto de la herramienta — es estructural, y esta lección la nombra con precisión.

Conexión con el módulo

Las lecciones 4 y 5 confirmaron, con ejecución real, hasta dónde llega Infracost. Esta lección explica por qué llega exactamente hasta ahí, con el mismo vocabulario que finops-and-cost-guardrails-guide ya instaló para Lambda y DynamoDB, llevado un paso más allá. La lección 7, inmediatamente después, construye la pieza que esta lección deja claramente definida como faltante.


Primero, la pregunta pendiente: ¿Infracost soporta Bedrock, aunque sea sin volumen?

La documentación pública de Infracost lista, categoría por categoría, qué recursos de Terraform de AWS tiene soporte para cotizar — verificado en infracost.io/docs/supported_resources/aws/ en el momento de escribir esta guía. Se buscó, específicamente, cualquier mención de bedrock, de sagemaker, o de cualquier categoría de Machine Learning / Inteligencia Artificial en esa página.

El resultado, verificado por lectura directa: ningún recurso aws_bedrock_* aparece en la lista de recursos soportados de Infracost, de pago ni gratuitos. No hay una categoría de "Machine Learning" ni de "AI" en la estructura de la página. La búsqueda de "bedrock" en esa documentación no devuelve resultados.

Esto contesta, con evidencia —no con el intento bloqueado de la lección 5—, la pregunta que quedó pendiente: aunque el gate de autenticación no hubiera bloqueado nada, aws_bedrock_guardrail muy probablemente habría aparecido sin precio, no porque Infracost haya decidido que Bedrock es usage-based sin volumen declarado (el mismo patrón que ya viste con Lambda y DynamoDB), sino porque el tipo de recurso en sí no está en su catálogo todavía. Es una categoría de ausencia distinta y más completa que la de la lección 5 de finops-and-cost-guardrails-guide, que sí encontró a DynamoDB y Lambda listados, solo que con su total marcado "Cost depends on usage".

   TRES NIVELES DE "SIN PRECIO", DE MENOS A MÁS COMPLETO

   1. Recurso soportado, con precio fijo                 aws_instance (EC2)
      -> Infracost da un número completo, sin nada adicional.

   2. Recurso soportado, *usage-based*, sin volumen       aws_lambda_function,
      declarado                                           aws_dynamodb_table
      -> Infracost sabe QUÉ eje factura (invocaciones,
         unidades de lectura/escritura), pero no CUÁNTO --
         "Cost depends on usage". finops-and-cost-guardrails-
         guide resuelve esto con infracost-usage.yml (M2.6).

   3. Recurso NO soportado en el catálogo                 aws_bedrock_guardrail
      -> Infracost ni siquiera tiene un eje de facturación
         que ofrecer. No hay campo que llenar con un
         supuesto de volumen -- el catálogo no reconoce
         el tipo de recurso en absoluto.

Por qué el nivel 3 es distinto, y más difícil, que el nivel 2

finops-and-cost-guardrails-guide ya resolvió el nivel 2 con un mecanismo real, documentado en su Módulo 2, lección 6: infracost-usage.yml, un archivo donde declaras, para cada recurso usage-based que Infracost sí reconoce, un supuesto de volumen —monthly_write_request_units para DynamoDB, monthly_requests para Lambda—. Infracost lee ese archivo, lo combina con el precio por unidad que ya conoce, y produce un total. Es un mecanismo real, y vale la pena entender exactamente qué necesita para funcionar: necesita que el tipo de recurso ya esté en el catálogo, con sus ejes de facturación ya modelados por Infracost. El archivo de uso solo llena el número que falta —no le enseña a Infracost qué es un recurso que nunca vio antes.

aws_bedrock_guardrail falla antes de esa etapa. No es que falte un archivo de uso — es que no hay, todavía, ninguna definición en el catálogo de Infracost de qué ejes de facturación tiene ese tipo de recurso, ni de si el propio recurso aws_bedrock_guardrail representa siquiera algo facturable (de hecho, no lo es: un guardrail en sí no genera un cargo por existir — el cargo real vendría de una invocación posterior de bedrock-runtime:InvokeModel, un llamado que ni siquiera se hace a través de un recurso de Terraform).


El problema de fondo: ninguna invocación tiene un recurso de Terraform que la represente

Esta es la pieza central de esta lección, la que ninguna versión futura del catálogo de Infracost —ni siquiera si algún día agrega soporte completo para aws_bedrock_guardrail— podría resolver por sí sola. Repasa qué es, exactamente, lo que Terraform declara sobre la carga de IA de Andes Cargo:

   QUÉ SÍ ESTÁ EN andes-cargo-infra/           QUÉ NUNCA VA A ESTAR AHÍ

   aws_bedrock_guardrail                       Cada llamada individual a
   (una política de contenido,                 bedrock-runtime:InvokeModel
    declarada una sola vez)                    que extract-shipment-manifest-
                                                fields hace en tiempo de
   aws_iam_role                                ejecución -- una por cada
   (el rol que AUTORIZA invocar,                evento ManifestParseFailed
    declarado una sola vez)                     que llega, con un contenido
                                                distinto cada vez.
   aws_lambda_function
   (el handler que CONTIENE la
    lógica de invocación,
    declarado una sola vez)

Compara esto con Lambda o DynamoDB, donde el mecanismo de infracost-usage.yml sí funciona: aws_lambda_function es el mismo recurso que Terraform declara Y el mismo recurso que AWS factura por invocación — hay una correspondencia uno a uno entre "lo que está en el plan" y "lo que genera la factura". Con Bedrock, esa correspondencia se rompe: lo que Terraform declara (aws_bedrock_guardrail, el rol IAM, la función Lambda que hace la llamada) es configuración e infraestructura de soporte. Lo que AWS factura —cada llamada InvokeModel, con su conteo específico de tokens de entrada y de salida— ocurre completamente por fuera de Terraform, en tiempo de ejecución, orquestada por código Python dentro del handler de la función Lambda, no por ningún recurso declarado.

Ninguna herramienta que lea únicamente HCL o un tfplan.json puede resolver esto — no por una limitación de Infracost específicamente, sino porque el dato que falta (cuántos tokens va a procesar cada invocación futura) no vive en ningún artefacto de infraestructura como código. Es la diferencia exacta que la lección 1 de este módulo ya anticipó: Lambda y DynamoDB son usage-based en volumen (cuántas veces), Bedrock es usage-based en volumen y en contenido (cuántas veces, y cuánto texto cada vez) — y ese segundo eje jamás aparece en un plan de Terraform, sin importar qué tan completo sea el catálogo de precios de la herramienta que lo lea.


Qué SÍ puede resolver esto: un supuesto declarado, no una herramienta más inteligente

La conclusión de esta lección no es "hace falta una herramienta mejor que Infracost". Es que el dato faltante —tokens de entrada promedio, tokens de salida promedio, volumen mensual de invocaciones— es una decisión de producto declarada por un humano, no algo que ninguna herramienta de análisis estático pueda inferir leyendo código. finops-and-cost-guardrails-guide ya demostró esto mismo, a menor escala, con infracost-usage.yml: el archivo no calcula el volumen de Lambda, alguien lo declara, basado en una hipótesis de negocio documentada en COST-PROFILE.md.

La lección 7 de este módulo construye exactamente esa pieza: una calculadora propia, en Python, que toma como entrada explícita —nunca inferida, nunca asumida por defecto— el tamaño promedio de una invocación y el volumen mensual esperado, junto con el precio público citado en la lección 2, y produce una proyección de costo determinista. No reemplaza a Infracost — resuelve la parte del problema que Infracost, por diseño, no puede tocar: el supuesto de volumen y contenido que solo un humano con conocimiento del negocio de Andes Cargo puede declarar.


Errores comunes

Esperar que un futuro soporte de Infracost para aws_bedrock_* resuelva el problema completo (de expectativa sobre la herramienta, no sobre el dato). Qué pasa: alguien concluye que, si Infracost algún día agrega aws_bedrock_guardrail a su catálogo, el problema de costear extract-shipment-manifest-fields desaparecería por completo. Cómo detectarlo: si tu conclusión de esta lección es "hay que esperar a que Infracost se ponga al día". Cómo corregirlo: aunque Infracost agregara mañana mismo soporte completo para aws_bedrock_guardrail, seguiría enfrentando el mismo problema de fondo que esta lección nombró: ninguna invocación individual de InvokeModel tiene un recurso de Terraform correspondiente. El soporte del catálogo resolvería, en el mejor caso, un infracost-usage.yml con un campo de "tokens de entrada promedio" y "tokens de salida promedio" que declarar — exactamente el mismo tipo de supuesto humano que la calculadora de la lección 7 ya construye, con o sin Infracost.

Confundir "Infracost no tiene aws_bedrock en su catálogo" con "Infracost es una mala herramienta" (de juicio injusto sobre alcance). Qué pasa: alguien, después de esta lección, concluye que Infracost está incompleto o mal mantenido. Cómo detectarlo: si tu reacción es descartar Infracost como herramienta confiable para el resto de este ecosistema. Cómo corregirlo: Infracost soporta más de mil recursos de Terraform en AWS, Azure y Google Cloud —una cobertura enorme para infraestructura tradicional—, y sigue siendo la herramienta correcta para todo lo que este ecosistema ya construyó (S3, Lambda, DynamoDB, EC2, y decenas más). Que un servicio relativamente nuevo y con un modelo de facturación genuinamente distinto (Bedrock, con costo por contenido de cada invocación) todavía no esté en su catálogo es una limitación de cobertura específica, no una falla general de la herramienta.

Pensar que el problema de esta lección es exclusivo de Bedrock, y no se repetiría con cualquier otro servicio de IA generativa (de alcance estrecho). Qué pasa: alguien asume que este hueco es una peculiaridad de Bedrock específicamente, y que otro proveedor de LLM resolvería el problema de estimación por sí solo. Cómo detectarlo: si tu razonamiento es "esto no pasaría si usáramos otro servicio de IA". Cómo corregirlo: el problema de fondo —que el costo depende del contenido de cada invocación, no de un recurso declarado en infraestructura como código— es inherente a cualquier API de inferencia de LLM facturada por token, sea Bedrock, una API directa de un proveedor de modelos, o cualquier otro servicio gestionado con el mismo modelo de precio. No es un defecto de Bedrock ni de AWS — es la naturaleza de facturar por contenido variable en vez de por infraestructura fija.


Ejercicios

Ejercicio 1 — Explica, con tus propias palabras, la diferencia entre el "nivel 2" y el "nivel 3" de la tabla de esta lección, usando a Lambda y a Bedrock como ejemplo de cada uno. Un colega, después de leer sobre infracost-usage.yml, pregunta por qué ese mismo mecanismo no serviría directamente para Bedrock. Explícale la diferencia con el ejemplo de esta lección.

Ver solución

Lambda (nivel 2) está en el catálogo de Infracost, con sus ejes de facturación (invocaciones, duración) ya modelados — lo único que falta es el número de invocaciones esperadas, que infracost-usage.yml provee. Bedrock (nivel 3), verificado en esta lección, ni siquiera está en ese catálogo — no hay ejes de facturación modelados en absoluto para aws_bedrock_guardrail, así que no hay ningún campo de infracost-usage.yml que pudiera llenarse para resolverlo, incluso si alguien lo intentara. Un archivo de uso completa un hueco en un modelo que ya existe; no puede crear un modelo que Infracost todavía no tiene.

Ejercicio 2 — Explica por qué "ninguna invocación de Bedrock tiene un recurso de Terraform que la represente" es un problema distinto del "usage-based sin volumen declarado" que ya viste con DynamoDB. ¿En qué se diferencia estructuralmente, más allá de que uno tiene un archivo de uso disponible y el otro no?

Ver solución

aws_dynamodb_table en modo PAY_PER_REQUEST es, literalmente, el mismo objeto que AWS factura por unidad de lectura/escritura — hay una correspondencia directa entre el recurso declarado en HCL y la línea de la factura. Lo único que falta es cuántas de esas unidades va a haber. Con Bedrock, no existe ningún recurso de Terraform que sea "una invocación" — aws_bedrock_guardrail es una política de configuración, no un objeto que se invoca; la invocación real ocurre en código Python, dentro de un handler Lambda, en tiempo de ejecución, completamente fuera de cualquier archivo .tf. La diferencia no es solo "falta un número" — es que no hay ningún recurso declarado que sea, siquiera conceptualmente, el objeto que se está facturando.

Ejercicio 3 — Predice qué tipo de dato va a pedir la calculadora de la lección 7, basándote en la conclusión de esta lección. Sin haber leído todavía la lección 7, ¿qué tipo de información crees que va a tener que declarar un humano, explícitamente, para que esa calculadora funcione?

Ver solución

Basándote en la conclusión de esta lección —que el problema es de contenido (tokens por invocación) y de volumen (cuántas invocaciones), y que ninguno de los dos puede inferirse de Terraform—, es razonable predecir que la calculadora va a pedir, como mínimo: el número promedio de tokens de entrada por invocación (el tamaño típico de un manifiesto en texto libre), el número promedio de tokens de salida (el tamaño típico de la respuesta del modelo con los campos extraídos), y el volumen mensual esperado de invocaciones (cuántos eventos ManifestParseFailed se esperan por mes). Los tres son, exactamente, supuestos declarados por un humano con conocimiento del negocio de Andes Cargo — nunca inferidos de ningún archivo de infraestructura.


Resumen y siguiente paso

Esta lección contestó, con evidencia de la documentación pública de Infracost, la pregunta que la lección 5 dejó pendiente: aws_bedrock_guardrail no aparece en el catálogo de recursos soportados de Infracost —ninguna categoría de Machine Learning o IA existe todavía en esa lista—. Pero fue un paso más allá: incluso si ese soporte existiera, el problema de fondo seguiría sin resolverse, porque ninguna invocación individual de un modelo de Bedrock tiene un recurso de Terraform que la represente — el costo depende del contenido de cada llamada en tiempo de ejecución, un dato que no vive en ningún archivo de infraestructura como código, sin importar cuán completo sea el catálogo de precios de la herramienta que lo lea.

Antes de avanzar deberías poder: explicar los tres niveles de "sin precio" de esta lección, con un ejemplo real de cada uno; explicar por qué infracost-usage.yml no serviría, aunque quisieras usarlo, para aws_bedrock_guardrail; y anticipar qué tres datos, como mínimo, va a necesitar declarar explícitamente la calculadora de la lección 7.

La lección 7 construye esa calculadora — código Python real, determinista, corrido con pytest sobre casos fijos — la pieza que resuelve exactamente lo que esta lección dejó definido como estructuralmente fuera del alcance de cualquier herramienta de análisis de infraestructura como código.

Recursos

  1. Infracost — Supported resources: AWS — la fuente verificada de que ningún recurso aws_bedrock_* aparece en el catálogo de Infracost al momento de escribir esta guía.
  2. finops-and-cost-guardrails-guide, Módulo 2, lección 6 (06-usage-based-resources-and-the-usage-file.md) — la fuente de infracost-usage.yml, el mecanismo que esta lección explica por qué no alcanza para Bedrock.
  3. AWS Docs — InvokeModel — referencia de la operación real que factura Bedrock, la que nunca aparece como un recurso de Terraform.
  4. Este módulo, lección 1 — la distinción original entre usage-based en volumen y usage-based en contenido, que esta lección desarrolla en profundidad.