On-demand vs. provisioned throughput, batch inference, selección de modelos y token caching — con números reales.
TL;DR — Cinco estrategias que se combinan para lograr ahorros del 60-80% en Bedrock:
- Batch inference para workloads asíncronos → 50% de descuento, sin impacto en la calidad
- Prompt caching para contexto repetido → 90% más barato en input tokens cacheados
- Model routing (modelos económicos para tareas simples) → 40-70% de reducción de costos
- Benchmarking + LLM-as-a-judge para validar que los modelos más baratos son lo suficientemente buenos
- Observabilidad (OTel + DoiT GenAI Intelligence) para detectar drift y mantener los ahorros en el tiempo
A un cliente lo llevamos de $40K/mes a $18K con este playbook. Los detalles, abajo.
Lidero el equipo de Engineering de APAC en DoiT. El trimestre pasado, un cliente del sector financiero me pidió revisar su gasto en Bedrock. Estaban usando Claude Sonnet para todo — clasificación de tickets, extracción de documentos, chat con clientes — y su factura mensual había crecido sin que nadie lo notara hasta superar los $40K. Dos semanas después, la teníamos en $18K sin tocar la calidad de las respuestas.
Este es ese playbook. Si eres responsable de los costos de Bedrock en un equipo de Engineering o de datos, estas son las palancas que de verdad mueven la factura.
Los ejemplos de clientes en este artículo son composiciones basadas en patrones recurrentes en múltiples engagements — no son casos individuales.
Entendiendo los dos modelos de precios
Bedrock tiene dos modelos de precios, y he visto errores costosos en ambos sentidos. (Para un desglose detallado de cómo funcionan los precios de Bedrock — incluyendo costos de fine-tuning, estimación de tokens y estrategias de tagging — revisa la guía de CloudOps sobre precios de Bedrock de Josh Palmer. Este artículo se centra en las decisiones de Engineering que reducen la factura.)
Precios On-Demand
Pagas por token — input y output, con precios separados. Sin compromiso, sin mínimo.
Elige esta opción cuando tu uso es irregular, todavía estás experimentando, o tu gasto mensual está por debajo del punto de cruce (más sobre esto abajo).
Lo que suele tomar a la gente por sorpresa: los output tokens normalmente cuestan entre 3 y 5 veces más que los input tokens. ¿Ese cliente del sector financiero que mencioné? Estimaban costos basándose solo en el precio de los input tokens y subestimaban su factura real casi 3 veces. Una tarea que consume 1.000 input tokens pero genera 2.000 output tokens está dominada por el costo de salida. Modela siempre los dos lados.
Provisioned Throughput
Compras model units por hora (o con commitments de 1 mes/6 meses). Un model unit es la unidad de capacidad reservada de Bedrock — piénsalo como "un carril en la autopista" que pagas por hora lo uses o no.
Elige esta opción cuando tienes workloads sostenidos y predecibles, tu utilización supera de forma consistente el umbral de cruce y necesitas latencia garantizada.
El año pasado trabajé con una empresa de medios que tenía provisioned throughput corriendo al 15% de utilización. Lo habían configurado durante una prueba de carga, se les olvidó volver atrás y estuvieron quemando dinero durante tres meses antes de que alguien se diera cuenta. Cambiarlos a on-demand fue un ajuste de configuración de una sola línea que les ahorró miles de dólares al instante. Provisioned throughput con baja utilización es el error más caro en Bedrock.
Cómo encontrar el punto de cruce
Costo mensual on-demand = (input_tokens × input_price) + (output_tokens × output_price)Costo mensual provisioned = model_units × hourly_rate × 730 horasPara la mayoría de los modelos, provisioned se vuelve más barato alrededor del 60-70% de utilización sostenida de un model unit. La palabra "sostenida" carga con todo el peso aquí — no mires el uso pico. Tráfico que se mantiene cerca del 70% todo el día con pequeños picos es un buen candidato; tráfico que está al 10% y sube al 100% durante cinco minutos cada hora no lo es.
Batch Inference: el 50% de descuento que casi nadie aprovecha
Este es probablemente mi tema favorito al hablar con clientes, porque la reacción siempre es la misma: "Espera, ¿podemos simplemente... pagar la mitad?".
Sí. Bedrock cobra los batch tokens al ~50% de las tarifas on-demand para los modelos compatibles. Mismos modelos, misma calidad, mitad de precio. (Al momento de escribir esto — revisa la página de pricing antes de apostar un roadmap a esa cifra.) El tradeoff es un SLA de 24 horas sin streaming — tus jobs entran a una cola y se completan de forma asíncrona.
Cualquier workload que no necesite respuesta en tiempo real es candidato. Categorizar tickets de soporte, procesar corpus de documentos para RAG, generar descripciones de producto, ejecutar suites de evals, extraer datos estructurados de documentos no estructurados. Estimaría que la mayoría de los equipos tiene entre un 30 y 40% de su workload de Bedrock que podría moverse a batch sin ningún impacto visible para el usuario.
Así se ve concretamente. Toma 10.000 requests con un promedio de 500 input tokens y 200 output tokens cada uno, usando Claude Sonnet (precios on-demand en ap-southeast-2):
| Modo | Costo Input | Costo Output | Total |
|---|---|---|---|
| On-demand | $15.00 | $37.50 | $52.50 |
| Batch | $7.50 | $18.75 | $26.25 |
$26.25 ahorrados en una sola corrida batch. Los pipelines diarios elevan eso a miles al mes. Y la implementación son apenas archivos JSONL en S3 — es un cambio de plomería, no de arquitectura.
La selección de modelos como estrategia de costos
Elegir el modelo correcto es una decisión de costo con una varianza de 10 a 60 veces. La mayoría de los equipos usa por defecto algo más caro de lo que necesita porque lo eligió durante el prototipado y nunca revisó la decisión.
La arquitectura por niveles
Las implementaciones de Bedrock más eficientes en costos que he visto usan niveles:
- Tier 1 (Haiku, Mistral 7B, Llama 3 8B) — clasificación, routing, extracción, Q&A simple. Fracciones de centavo por request. Debería manejar entre el 60 y 80% de tu tráfico.
- Tier 2 (Sonnet, Mistral Large, Llama 3 70B) — razonamiento complejo, generación con matices. De 5 a 10 veces más barato que el tier superior.
- Tier 3 (Opus, Claude 3.5 Sonnet) — solo las tareas más difíciles. Precio premium, reservado para trabajo que de verdad lo amerita.
El patrón Router
Bedrock tiene una solución integrada solo para routing dentro de la misma familia. Intelligent Prompt Routing te da un único endpoint serverless que rutea requests entre modelos de la misma familia según la complejidad del prompt. Especificas un ARN de familia de modelos (por ejemplo, Anthropic Claude), y Bedrock decide si cada request va a Haiku o a Sonnet. AWS asegura reducciones de costo de hasta el 30% — por lo que he visto con clientes, esa es una cifra razonable. Cero código personalizado, simplemente cambias tu model ID por el ARN del prompt router.
Para routing entre familias (Haiku para clasificación, Mistral para extracción, Sonnet para razonamiento complejo), tienes que construir algo tú mismo. Y siendo honesto, eso es lo que hace la mayoría de los equipos en producción. No existe un framework off-the-shelf maduro que resuelva esto lo suficientemente bien como para recomendarlo sin reservas.
Tres patrones que funcionan, aproximadamente en orden de madurez:
Clasificación basada en reglas es por donde la mayoría de los equipos empieza y donde muchos se quedan. Escribe entre 5 y 10 reglas basadas en señales estructurales — palabras clave del tipo de tarea, longitud del input, formato esperado de salida, profundidad de la conversación. Sin ML, sin dependencias, desplegable en un día. Resuelve correctamente el 70-80% de las decisiones de routing. Son apenas unos cientos de líneas de lógica condicional.
Cascading basado en confianza es el patrón con mayor ROI que he visto. Envía cada request al modelo más barato primero. Revisa la respuesta en busca de lenguaje evasivo, output mal formado o campos requeridos faltantes. Si falla, escala al siguiente tier. Cuenta con la latencia adicional de una llamada al modelo en aproximadamente el 5-15% de los requests escalados. Un equipo con el que trabajé — una plataforma de e-commerce que procesa consultas de productos — pasó de $38K/mes a $15K/mes con este enfoque. Su tasa de escalación fue solo del 8%. No necesitas que el clasificador sea perfecto; necesitas que acierte lo suficiente como para que la escalación se haga cargo de las excepciones. Si tu tasa de escalación se va por encima del 25-30%, arregla el clasificador.
Reglas híbridas + clasificador ML es el paso de graduación. Una vez que tienes algunas semanas de tráfico productivo con resultados etiquetados, entrena un clasificador pequeño (DistilBERT o regresión logística sobre TF-IDF) que añade <5ms de latencia. El clasificador en sí debería sumar milisegundos de un solo dígito; el costo real es la disciplina de Engineering de etiquetar datos y reentrenar periódicamente. Los equipos que lo hacen suelen mejorar la precisión del routing de ~78% a ~91%.
Miré con detenimiento los frameworks existentes. RouteLLM, del equipo de LMSys, tiene respaldo de investigación pero es fundamentalmente un router de dos modelos entrenado con datos de chat general — para workloads de Bedrock específicos de un dominio, tendrías que reentrenar. LiteLLM es excelente para infraestructura (API unificada, fallbacks, reintentos), pero su routing es load balancing, no selección de modelos basada en calidad. Ninguno es una solución plug-and-play para el problema entre familias.
Empieza con Intelligent Prompt Routing. Cuando tengas evidencia de que el routing entre familias ahorraría dinero significativo, construye un clasificador basado en reglas. Es predecible, depurable, y los equipos con los que trabajo que han tomado este camino reportan de forma consistente reducciones de costo del 40-70%.
Benchmarking de calidad vs. costo de modelos
No asumas que necesitas el modelo más caro. Ejecuta tus tareas reales en múltiples modelos y mide la precisión en tu caso de uso específico, el costo por tarea (no por token) y la latencia.
Hicimos este ejercicio con el cliente del sector financiero. Su tarea de clasificación de tickets obtuvo un 94% de precisión en Haiku vs. 97% en Sonnet — a 1/15 del costo. Esa diferencia del 3% no importaba para su caso de uso. Los números variarán para el tuyo, pero el patrón se repite: haz benchmarking antes de comprometerte.
Automatizar la evaluación de calidad con LLM-as-a-Judge
Para clasificación o extracción puedes validar la calidad programáticamente, pero para generación abierta — resúmenes, explicaciones, respuestas a clientes — la evaluación tradicionalmente requería revisores humanos. Eso no escala.
Bedrock tiene una respuesta integrada: evaluación de modelos con LLM-as-a-judge. Proporcionas un dataset de prompts (opcionalmente con respuestas de ground truth), eliges un modelo evaluador, y Bedrock pasa los outputs del modelo candidato por el juez con métricas como corrección, completitud, utilidad, coherencia, relevancia y seguridad. Corre como un job gestionado — recibes puntajes por prompt y agregados, almacenados en S3.
El objetivo es probar que un modelo que cuesta entre 5 y 15 veces menos por token sea "suficientemente bueno" antes de mover tráfico real. Prepara un archivo JSONL con tus prompts representativos, ejecuta el mismo job de evaluación contra Haiku, Sonnet y cualquier otro que estés considerando, y compara los puntajes lado a lado. AWS publicó un walkthrough con ejemplos de código y hay un Jupyter notebook complementario en GitHub.
Algunas cosas que he aprendido usando esto con clientes.
Usa el mismo modelo evaluador en todas las comparaciones — si juzgas el output de Haiku con un modelo y el de Sonnet con otro, estás midiendo diferencias del evaluador, no diferencias entre modelos.
Incluye tus prompts reales de producción, no benchmarks genéricos. MT-Bench está bien para una verificación rápida, pero tus prompts de clasificación de tickets se comportarán distinto a un question-answering académico.
La evaluación misma cuesta dinero (el modelo juez procesa cada output), así que empieza con 200-500 prompts representativos en lugar de tu dataset completo. Eso suele ser suficiente para ver si el modelo barato es claramente peor, claramente aceptable o "requiere más investigación".
El ground truth es opcional pero valioso — para tareas donde tienes outputs conocidos como buenos, las métricas de fidelidad y corrección se vuelven mucho más significativas.
benchmark_bedrock.py captura costo y latencia; LLM-as-a-judge puntúa la calidad. Ejecuta ambos y tendrás el panorama completo de costo vs. calidad sin revisión manual.
Prompt Caching: 90% de ahorro en contexto repetido
Me sorprende lo pocos equipos que tienen esto habilitado. Los input tokens cacheados se facturan con un 90% de descuento sobre el precio estándar.
Cuando envías un request con caching habilitado, Bedrock almacena el prefijo de tu prompt. Los requests subsecuentes que comparten ese prefijo aciertan en el caché. Los hits de caché cuestan ~10% de la tarifa normal. Las escrituras al caché (primer request) cuestan ligeramente más, así que solo se ahorra dinero cuando reutilizas el mismo prefijo varias veces — pero si tienes un system prompt o ejemplos few-shot, el retorno es inmediato.
Donde brilla: system prompts de más de 1.500 tokens, ejemplos few-shot estáticos, contexto de documento compartido en aplicaciones RAG, historial de conversación multi-turno.
Los números hablan por sí solos. Un system prompt de 2.000 tokens con 10.000 requests/día en Claude Sonnet:
| Escenario | Costo Diario (porción del system prompt) |
|---|---|
| Sin caching | 2.000 × 10.000 × $0.003/1K = $60.00 |
| Con caching (99% hit rate) | ~$7.00 |
$53/día. Más de $1.500/mes. Solo en el system prompt. Recorrí este cálculo con un cliente el mes pasado y habilitaron el caching antes de que terminara nuestra llamada.
Detalles a tener en cuenta:
- La longitud mínima del prefijo cacheable varía según el modelo (típicamente 1.024-2.048 tokens)
- Coincidencia exacta de prefijo — los espacios en blanco y el orden importan
- TTL / expiración tras inactividad (tu caché se enfría si baja el tráfico)
- No todos los modelos soportan caching todavía — revisa la documentación actual
Cómo construir un framework de benchmarking
Tus decisiones de optimización deberían guiarse por datos de tus workloads reales. Esto es lo que mi equipo recomienda.
Para cada modelo y configuración que pruebes, captura: costo por tarea, conteo de input/output tokens, latencia (tiempo al primer token y total) y un puntaje de calidad específico de la tarea.
El proceso: elige entre 3 y 5 tareas que representen tu mix real de workload, crea entre 100 y 500 ejemplos de prueba por tarea con outputs conocidos como buenos, ejecuta cada tarea en cada modelo candidato, calcula el costo por tarea (no por token — los modelos tokenizan distinto) y grafica costo vs. calidad para encontrar el codo de la curva. Hasta un scatter plot básico es suficiente — estás buscando "misma calidad, mucho más barato" o "calidad ligeramente peor, dramáticamente más barato".
Armé un script de Python (benchmark_bedrock.py) que automatiza esto — corre prompts en múltiples modelos de Bedrock, registra conteos de tokens y latencia, exporta CSV, imprime estadísticas resumen. Hazle fork y adáptalo a tus workloads.
Al interpretar los resultados, busca modelos donde la calidad se aplana (Haiku al 93% vs. Sonnet al 95% — ¿vale ese 2% pagar 10 veces más?), outliers de latencia, diferencias de eficiencia en tokens (un modelo más barato por token pero 2 veces más verboso no es realmente más barato) y candidatos para batch.
Visibilidad unificada de costos GenAI con DoiT GenAI Intelligence
La mayoría de los equipos con los que trabajo no solo usa Bedrock. Tienen OpenAI para algunos workloads, Anthropic directo para otros, tal vez Vertex AI en un proyecto de GCP. Los datos de costos terminan dispersos en cuatro consolas con dimensiones incompatibles.
Construimos GenAI Intelligence para resolver esto. Consolida datos de costo y uso de IA de Bedrock, Vertex AI, Azure ML, Databricks, Anthropic y OpenAI en una vista única normalizada. Tu gasto en Bedrock aparece junto a todo lo demás. Sin ETL personalizado.
Para Bedrock, el valor está en las etiquetas normalizadas. Model / Model Family rastrea el costo por modelo entre proveedores. Usage Type desglosa el gasto en input vs. output tokens — la división que la mayoría de los equipos subestima. Cached muestra si las operaciones usaron tokens cacheados, para que puedas medir el ROI del caching desde los datos de facturación. GenAI Spend marca todos los costos de IA generativa sin importar el proveedor para el seguimiento total del presupuesto.
Puedes hacer preguntas como "¿Cuánto nos ahorraron los tokens cacheados en Claude Sonnet el mes pasado?" o "¿Cuál es nuestra distribución de gasto entre Haiku y Sonnet para clasificación de tickets?" — entre proveedores, en un solo lugar.
El dashboard viene con reportes preconfigurados: gasto por proveedor (mensual), costo por familia de modelo (diario para los últimos 14 días — detecta picos rápido), desglose de tokens por modelo (30 días), y uso horario de tokens por proveedor (últimos 2 días — útil para correlacionar con despliegues). Como los datos de GenAI fluyen hacia nuestro motor de Cloud Analytics, también obtienes presupuestos, asignaciones, detección de anomalías y forecasting sobre tu gasto de IA.
Digamos que estás corriendo Haiku para clasificación y Sonnet para razonamiento, con caching en ambos:
| Modelo | Cached | Costo Mensual | Uso de Tokens |
|---|---|---|---|
| Claude Haiku | true | $45 | 18M tokens |
| Claude Haiku | false | $320 | 12M tokens |
| Claude Sonnet | true | $180 | 4M tokens |
| Claude Sonnet | false | $2,100 | 6M tokens |
La tasa de hit del caché de Haiku es sólida (60% de tokens cacheados). La de Sonnet, pobre (40%). Arreglar el caching de Sonnet podría ahorrar cientos al mes — y lo detectaste sin escribir una sola query de CloudWatch.
Para empezar: conecta tu cuenta de AWS a DoiT, ve a Dashboards → GenAI Intelligence, y tus datos de Bedrock se cargan automáticamente. No se necesita instrumentación del lado de Bedrock.
Observabilidad con OpenTelemetry
El benchmarking te da una foto en un momento. Los workloads productivos derivan — los prompts cambian, los patrones de tráfico se desplazan, salen modelos nuevos. GenAI Intelligence cubre el lado de facturación de la visibilidad continua. Para instrumentación a nivel de aplicación — latencia, decisiones de routing, hits de caché por request — recomiendo OpenTelemetry.
Las convenciones semánticas de GenAI hacen que cualquier backend compatible con OTel (Grafana, Datadog, Honeycomb) entienda tus spans. Envuelve cada invocación a Bedrock en un span con estos atributos:
gen_ai.system—"aws.bedrock"gen_ai.request.model— el ID del modelogen_ai.usage.input_tokens/output_tokens— desde la metadata de la respuestagen_ai.usage.cost— calculado desde tu tabla de preciostask.type— el nombre de la tarea a nivel de aplicación
Lo que obtienes: tendencias de costo-por-tarea en el tiempo (detecta drift de prompts antes de que llegue a tu factura), validación del routing de modelos (el Tier 1 de un cliente estaba manejando el 40% en lugar del 70% esperado — un bug que costaba $800/mes extra) y monitoreo de tasa de hit de caché (detecta caídas en horas, no al final del ciclo de facturación).
También obtienes los datos para correlacionar con ModelUnitUtilization de CloudWatch para decisiones de provisioned throughput.
Instrumentación mínima:
from opentelemetry import trace
tracer = trace.get_tracer("bedrock-client")
def invoke_with_telemetry(client, model_id, prompt, max_tokens, task_type="unknown"): with tracer.start_as_current_span("bedrock.invoke") as span: span.set_attribute("gen_ai.system", "aws.bedrock") span.set_attribute("gen_ai.request.model", model_id) span.set_attribute("gen_ai.request.max_tokens", max_tokens) span.set_attribute("task.type", task_type)
resp = client.invoke_model(modelId=model_id, body=body, contentType="application/json") data = json.loads(resp["body"].read())
in_tok = data["usage"]["input_tokens"] out_tok = data["usage"]["output_tokens"] span.set_attribute("gen_ai.usage.input_tokens", in_tok) span.set_attribute("gen_ai.usage.output_tokens", out_tok)
return dataDe ahí, construye cuatro paneles — costo diario por modelo, costo por tarea por modelo, tasa de hit de caché, latencia p50/p95 — y revísalos semanalmente.
Errores comunes
Los errores que veo más seguido, en orden aproximado de cuánto dinero hacen perder:
Monitorea la utilización de provisioned throughput semanalmente. ¿Por debajo del 50% sostenido? Cambia a on-demand. Esa empresa de medios estaba perdiendo más dinero en capacidad provisionada inactiva que lo que gastaba en inferencia real.
Modela y limita los output tokens. Los output tokens cuestan entre 3 y 5 veces más que los input. Un equipo redujo sus costos de output un 40% solo agregando "responde en JSON, sin explicaciones" a sus prompts de extracción.
Pasa a batch todo lo que no necesite latencia menor a 24 horas. 50% de descuento. Sin compromiso en calidad.
No dejes que Sonnet sea el default. Usarlo para todo porque funcionó durante el prototipado es la forma más común de sobregasto que veo.
Activa el caching en cualquier punto donde reutilices prompts. ¿System prompt estático o ejemplos few-shot? Minutos de trabajo, ahorros inmediatos.
Mide por tarea, no por token. Un modelo más barato que produce salida más verbosa puede costar más por tarea. Haz benchmarking a nivel de tarea.
Juntando todo
El camino de optimización por el que llevo a la mayoría de los equipos:
- Batch inference — mueve los workloads asíncronos. Ahorro inmediato del 50%, sin impacto en la calidad.
- Prompt caching — actívalo para contexto repetido. Minutos de trabajo.
- Benchmarking de modelos alternativos — probablemente encontrarás que entre el 60 y 80% de tu workload corre bien en Tier 1.
- Model routing — construye un clasificador. Empieza con reglas.
- Provisioned throughput — solo después de que lo anterior esté estable y tu uso sea predecible.
Estos se suman. ¿El cliente del sector financiero que mencioné al principio? Hicieron los pasos 1-4 en seis semanas. Batch inference ahorró 22%. Caching ahorró 18%. Model routing ahorró otro 25%. Total: de $40K a $18K.
Ahora bien, esto no es un proyecto de una sola vez. El panorama de Bedrock cambia constantemente. Cuando salió Claude 3.5 Haiku, era significativamente mejor que Claude 3 Haiku al mismo precio aproximado — los equipos que tenían los IDs de modelo hardcodeados se perdieron la actualización durante meses. AWS ha ajustado los precios de Bedrock varias veces sin mucha fanfarria. Y tu propio workload deriva: los prompts se hacen más largos, se agregan nuevos tipos de tarea, las proporciones de tráfico cambian.
Lo que funciona: una revisión trimestral ligera. Vuelve a correr tus benchmarks contra cualquier modelo nuevo (toma una tarde con el script de benchmarking). Usa LLM-as-a-judge para validar que la calidad no haya retrocedido. Revisa tus dashboards de OTel buscando drift en el routing — ¿sigue el Tier 1 manejando el porcentaje de tráfico que esperas? ¿Cambió tu tasa de hit de caché?
Si estás en DoiT, GenAI Intelligence te mostrará tendencias de costo por modelo que dejan en evidencia cuándo algo se desplazó. La revisión completa toma medio día una vez que la has hecho la primera vez.
La empresa de medios que mencioné antes descubrió durante una de estas revisiones que un cambio de prompt había bajado silenciosamente su tasa de hit de caché del 94% al 61% — $2K/mes adicionales que nadie había notado.
Si estás en Bedrock hoy y quieres un segundo par de ojos sobre tu factura, con gusto la reviso — sobre todo si estás en APAC. Y si ya eres cliente de DoiT, tienes el dashboard de GenAI Intelligence — úsalo como punto de partida para esa revisión trimestral.
El script de benchmarking referenciado en este artículo está disponible en https://github.com/p-obrien/bedrock-cost-model-blog. Ejecútalo contra tus propios workloads para generar los datos que necesitas para tomar decisiones informadas.