El precio de Durable Objects parece simple hasta que se calcula el primer mes real. Tres componentes que interactúan, un nivel gratuito que parece generoso hasta que se mide la huella de memoria correcta y un límite de rendimiento que aparece mucho antes de lo que la mayoría de los ingenieros esperan cuando llegan las cifras de producción. Comprender la estructura antes de ponerla en producción ahorra una factura sorpresa y un rediseño arquitectónico bajo presión.
La estructura de costos escalonada
El plan Workers Paid es el requisito previo: $ 5 al mes, sin él, los DO no están disponibles. Desde allí:
Reclamaciones: $0,15/millón después del primer millón gratis por mes. Cada llamada a un código auxiliar DO cuenta como una solicitud. El trabajador que realiza el enrutamiento utiliza la cuota de solicitud de trabajadores normal, separada de esta.
Computación en GB-segundos: $12,50/millón de GB-segundos después de 400K gratis por mes. GB-segundo es la unidad de trabajo: memoria utilizada en GB multiplicada por el tiempo de ejecución en segundos. La huella de memoria mínima por instancia DO es de 128 MB (0,125 GB). Una solicitud que tarda 10 ms a 128 MB consume 0,00125 GB-segundo.
Almacenamiento: $0.20/GB-mes después de 1GB gratis. Acumulativo: si tiene 1000 DO con 10 KB cada uno, son 10 MB de almacenamiento, dentro del rango gratuito. Si persiste una cantidad mayor de datos por instancia, el costo de almacenamiento comienza a aparecer.
Alarmas: 0,15$/millón de invocaciones. La misma mesa que las solicitudes normales.
El cálculo real del nivel de computación gratuito
400 mil GB-segundo/mes es la cifra. Con un espacio mínimo de 128 MB por instancia, esto equivale a 3,2 millones de segundos de ejecución: aproximadamente 889 horas de DO activo por mes, distribuidas entre todos sus DO.
La cuenta que importa es por carga de trabajo, no por DO. Si tiene DO que procesan solicitudes de 10 ms a 128 MB, cada solicitud consume 0,00125 GB-segundo. El nivel gratuito cubre 320 millones de estas solicitudes, mucho más que el nivel gratuito de solicitudes (1 millón). El cuello de botella del plan gratuito, para cargas de trabajo con DO ligeros y rápidos, es la cuota de solicitudes, no la cuota de cómputo.
El escenario que invierte esta cuenta son los DO que mantienen un estado grande en la memoria. Si un DO carga un documento de 2 MB en la memoria para procesar ediciones colaborativas, su huella no es de 0,125 GB, sino más cercana a 0,127 GB, más la sobrecarga de aislamiento. Para los DO que cargan JSON de gran tamaño, búferes de imágenes para procesamiento o cachés locales de gran tamaño, el GB-segundo real crece con el tamaño del estado en memoria, no con el tiempo de ejecución de la solicitud.
¿Cuánto cuesta una carga de trabajo concreta? 1 millón de solicitudes de 100 ms a 128 MB: 100 000 GB-segundo = $1,25 en computación (dentro del nivel de computación gratuito, pero por encima del nivel gratuito de solicitudes: $0,15 × (1 − 1) = gratis si es el primer millón, $0,15 si es el segundo). En total: $1,25 de cálculo + $0,15 de solicitudes adicionales = $1,40 además de los $5 del plan.
El límite de rendimiento que aparece antes de lo esperado
La ejecución en serie garantiza la coherencia de los DO y su límite de rendimiento. Un DO procesa una solicitud a la vez. El rendimiento máximo por instancia es inversamente proporcional al tiempo promedio por solicitud.
La fórmula: rendimiento máximo (req/s) = 1000 ms / tiempo promedio por solicitud (ms).
Procesamiento de 5 ms por solicitud: 200 solicitudes/s por instancia de DO. Procesamiento de 10 ms: 100 solicitudes/s. Procesamiento de 50 ms (incluidas E/S como llamada a un servicio externo): 20 req/s.
Este límite parece alto hasta que tenga una característica popular que enrute todas las solicitudes al mismo ID de DO. Una sala de chat con 500 mensajes por segundo enviados al mismo DO pondrá en cola más de 300 mensajes por segundo si el tiempo de procesamiento promedio es de 4 ms. La latencia percibida por los clientes aumenta proporcionalmente al tamaño de la cola.
La solución es fragmentar. En lugar de derivar el ID de DO directamente de la sala o recurso, agrega un sufijo numérico basado en un hash del identificador:
const shardCount = 10; const shard = Math.abs(hashCode(roomId)) % shardCount; const id = env.ROOMS.idFromName(`room-${roomId}-shard-${shard}`);
Cada fragmento es una instancia de DO independiente, con su propio límite de rendimiento. La fragmentación funciona bien para operaciones en las que es necesario garantizar la coherencia solo dentro de un fragmento; si necesita coherencia global en todos los fragmentos de un recurso, la solución se vuelve más compleja.
Límites de almacenamiento sorprendentes
list() devuelve un máximo de 128 entradas por llamada. Este límite no está documentado de manera destacada, pero aparece cada vez que tienes un DO con más de 128 claves almacenadas y llamas a list() esperando el conjunto completo.
La paginación utiliza el cursor:
async listAll(): Promise<Map<string, unknown>> { const result = new Map<string, unknown>(); let cursor: string | undefined; while (true) { const batch = await this.ctx.storage.list({ cursor, limit: 128 }); for (const [key, value] of batch) { result.set(key, value); } if (batch.size < 128) break; cursor = [...batch.keys()].at(-1); } return result; }
Ignorar esto en desarrollo (donde los DO tienen pocos datos) y descubrirlo en producción con 500 claves es un error que silenciosamente produce resultados incorrectos: la aplicación recibe los primeros 128 elementos y actúa como si fueran todos.
Otro límite: las transacciones se limitan a una única instancia DO. No existe ninguna transacción atómica que modifique dos instancias DO diferentes. Si su diseño requiere atomicidad entre dos DO (por ejemplo, transferir crédito de un DO a otro), debe implementar un protocolo de confirmación de dos fases en la capa de aplicación, con compensación en caso de falla. En la mayoría de los casos, esto indica que es necesario revisar el diseño: o el estado debe vivir en el mismo DO o la operación no necesita una atomicidad estricta entre instancias.
Qué monitorear después de entrar en producción
La latencia de respuesta por DO ID es el indicador más directo de un cuello de botella en el rendimiento. Si los DO específicos tienen una latencia creciente mientras que otros se vuelven más rápidos, esos DO específicos están poniendo en cola solicitudes: candidatos para fragmentación.
El consumo de GB-segundo frente al número de solicitudes revela DO con una huella de memoria mayor de lo esperado. Si la proporción de GB-segundos/solicitud aumenta sin cambiar el tiempo de procesamiento, algún DO está cargando más estado en la memoria.
El almacenamiento por espacio de nombres muestra un crecimiento en los datos que puede estar acumulando sin una rutina de limpieza. Los DO que escriben en el almacenamiento sin borrarlos acumulan datos indefinidamente: $0,20/GB-mes parece barato hasta que tienes unos pocos GB de datos históricos a los que ya nadie accede.
Donde $5/mes generan más
La base de $5/mes cubre el plan Pagado. Para aplicaciones pequeñas con uso dentro de los niveles gratuitos, este es el costo total. Para las aplicaciones que crecen, el costo marginal de las tres dimensiones (solicitudes, computación, almacenamiento) crece de diferentes maneras según el tipo de carga.
Cargas de solicitudes frecuentes pero procesamiento ligero: el nivel de solicitud se agota antes de que se calcule. Solución: compruebe si alguna de las solicitudes se puede almacenar en caché en la capa de trabajador antes de llegar al DO.
Cargas de procesamiento pesadas con pocas solicitudes: la computación domina. Solución: mida la huella de memoria real y el tiempo promedio de ejecución, y verifique si parte del cálculo se puede trasladar al trabajador que realiza el enrutamiento.
Muchos DO con datos persistentes: domina el almacenamiento. Solución: configure TTL para datos que no necesitan durar indefinidamente e implemente rutinas de limpieza a través de Alarm API.
Los límites más frecuentes en la producción son el rendimiento en serie y list(). El resto lo podéis encontrar en la documentación antes de ser una sorpresa. Estos dos los encuentras en los primeros días con tráfico real.
Lea también
- KV en producción: los patrones que funcionan y los que engañan al principio
- Objetos duraderos de Cloudflare: estado consistente en el borde: lo que realmente cambia
- D1 en producción: rendimiento, límites y lo que no escala por sí solo
- El modelo de programación de objetos duraderos: lo que se diferencia de cualquier cosa que haya usado alguna vez
- Objetos Durables y WebSockets: multijugador sin servidor dedicado
- Cuando los objetos duraderos son la respuesta incorrecta
