Math Challenge
Más

Arquitectura: qué corre, y cómo comprobarlo

Math Challenge corre enteramente sobre Cloudflare. Esta página separa lo que ya está corriendo de lo que solo está diseñado, y da el comando que comprueba cada afirmación.

Última comprobación contra producción:

Lo que está corriendo hoy

Todo lo demás del inventario está diseñado y no creado. Está listado más abajo, por nombre, porque una página que solo enseña las piezas que existen es un folleto.

HTTP/3, QUIC y 0-RTT

HTTP/3 sobre QUIC está encendido en la zona, y también la reanudación 0-RTT, que le permite a un visitante que regresa mandar la primera petición sin pagar un saludo nuevo. Ninguna de las dos se afirma a partir de una página de documentación: los dos renglones de abajo se leyeron directo de producción, con la misma comprobación que corre después de cada despliegue. Un interruptor que alguien apaga en un tablero no deja rastro en el repositorio: el código no se enteraría.

Leído de producción en la fecha de arriba:

alt-svc: h3=":443"; ma=86400
TLS 1.3 · Max Early Data: 14336

Lo que esto no arregla: HTTP/3 acelera el transporte, no el trabajo. Un paquete pesado de JavaScript bloquea el hilo principal sobre QUIC exactamente igual que sobre TCP. Por eso el presupuesto de peso de más abajo importa más que el protocolo.

RPC nativo entre Workers

Los dos Workers se hablan por un service binding, con llamadas a métodos tipados en vez de peticiones HTTP. Cloudflare describe lo que eso cuesta:

When you use Service Bindings, there is zero overhead or added latency. By default, both Workers run on the same thread of the same Cloudflare server.

RPC to another Worker (over a Service Binding) usually does not even cross a network. In fact, the other Worker usually runs in the very same thread as the caller, reducing latency to zero.

Cloudflare, documentación de Service Bindings y anuncio del RPC nativo de JavaScript

Un RPC que no cruza la red no puede ser superado por uno que sí, por eficiente que sea su serialización. El camino completo —primer Worker, segundo Worker, D1— responde en un endpoint público de salud, así que se puede comprobar en lugar de creerse.

Por qué no gRPC

gRPC se pidió por su nombre. La investigación lo descartó por tres hechos independientes, cada uno suficiente por sí solo:

  1. Workers no puede hacer llamadas gRPC salientes. El runtime no tiene streaming bidireccional de HTTP/2, y hay un issue abierto en el repositorio del propio runtime de Cloudflare que lo sigue.
  2. El navegador no habla gRPC. El cliente web implementa un protocolo distinto, cae a HTTP/1.1 —lo cual cancela algunas de las ventajas— y no soporta ni streaming de cliente ni llamadas bidireccionales.
  3. Los trailers de HTTP, que gRPC necesita para llevar el estado, tienen soporte limitado en el proxy de borde de Cloudflare. Lo documentó Cloudflare mismo.

Lo que quedó no es un premio de consolación. Adoptar gRPC aquí habría sido adoptar la generación anterior con más trabajo y menos resultado. La petición y la evidencia que la revirtió están las dos en la bitácora pública de decisiones: para eso sirve tener una.

Cero peticiones a terceros

Sin CDN de fuentes, sin script de analítica, sin marco embebido, sin hoja de estilo externa. Ni una petición sale hacia un servidor que no sea nuestro. Esto se comprueba contra el HTML que producción sirve de verdad, no contra nuestras intenciones.

Raleway está autoalojada como fuente variable, en dos archivos: latin y latin-ext. El segundo no es opcional: sin él, la ñ, la ç, la ã, la õ y la ü de cinco de nuestros locales caen a otra tipografía, justo en los caracteres que los hacen esos locales. Y la razón que pesa más que el rendimiento: cargar una fuente de un tercero le entrega a ese tercero la dirección y la firma del navegador de cada visitante, en las páginas públicas de un producto para niños.

La inferencia corre dentro de la red

Los 23 auditores adversariales ya corren sobre Workers AI, y el tutor va para allá también: la inferencia se queda en Cloudflare en vez de irse a una API externa. La llamada ocurre dentro del Worker, sin viaje externo, y el dispositivo de referencia es un teléfono Android de gama baja sobre datos móviles lentos, donde la latencia cuesta tanto como el precio.

Lo que eso cede está escrito en vez de maquillado. El modo JSON de Workers AI es de mejor esfuerzo, así que la validación de esquema nos toca a nosotros. Un veredicto que no valida cuenta como auditor fallido, jamás como auditor limpio: el modo de falla barato es volver a correrlo, y el caro es una violación que nadie vio.

Los intentos no van a D1

D1 topa en 10 GB por base de datos. Un renglón por intento llegaría a esa pared por error de diseño y no por crecimiento: el primer límite duro de esta arquitectura se alcanza equivocándose, no teniendo éxito. Los intentos crudos van a Analytics Engine; D1 se queda con las cuentas, los metadatos de contenido y los acumulados. Un auditor determinista bloquea el commit que se le olvide.

Medimos nosotros, y nunca sobre un niño

El rendimiento de campo lo medimos nosotros y nunca un tercero: un script en línea de unos 600 bytes que reporta a un endpoint nuestro, el cual escribe a Analytics Engine — jamás a D1 y jamás a un servicio de fuera. Nada de lo que manda identifica a una persona, y nunca se carga en la pantalla de un niño: el endpoint también rechaza esas bandas, así que los dos extremos fallan cerrados. Un auditor vigila el código; la comprobación de producción vigila la otra mitad, porque la plataforma puede inyectar una baliza propia a nivel de zona y eso no deja archivo que mirar.

Lo que pesan las páginas

Página más pesada: 9.5 KB comprimidos con gzip, que es como viajan. Todo el JavaScript de cliente del sitio: 2.6 KB. Todo el CSS: 1.5 KB. El presupuesto que bloquea un commit es de 12 KB por página y 60 KB para todo el JavaScript de cliente junto.

Medido en la fecha de arriba. Corre tú el auditor y obtienes el número en vez de nuestra palabra.

El presupuesto de rendimiento, y lo que todavía no afirmamos

El presupuesto es INP por debajo de 150 ms, LCP por debajo de 2.5 s y CLS por debajo de 0.1. 150 y no los 200 de costumbre, porque esto es un juego de alta frecuencia de interacción: un niño toca muchas veces por sesión y cada toque se mide. Es el perfil exacto donde INP se rompe.

Dicho sin adornos: eso son presupuestos, no resultados. Ninguna medición de campo lleva el tiempo suficiente para que el auditor que hace cumplir los umbrales tenga algo que hacer cumplir. Hasta entonces, esta página no afirma ningún resultado de rendimiento.

La flota de auditores

8 auditores deterministas corren en cada commit, en milisegundos, y lo bloquean. 23 auditores adversariales con modelos de lenguaje corren antes de abrir un PR, instruidos para encontrar la violación y no para aprobar. En total hay 39 planeados; 8 siguen esperando la fase que los habilita, y están listados como pendientes en vez de desaparecidos en silencio.

Dos reglas los hacen servir en vez de estorbar. Cada auditor tiene que citar la decisión o el documento de investigación que hace cumplir: uno que no pueda señalar un identificador real está opinando, y su veredicto no bloquea. Y anular a un auditor exige escribir por qué, en un archivo que se commitea junto al cambio que necesitó la anulación.

Lo que todavía no existe

El inventario se escribe antes de que los objetos existan, para que quien cree uno anote su renglón en la bitácora en el mismo PR. Un recurso creado y no documentado es un recurso que nadie va a poder borrar dentro de un año. Esto está diseñado y no creado:

Quién opera esto, y quién lo provee

Ignia opera la infraestructura. Cada objeto que esta página nombra vive en una cuenta de Cloudflare que opera Ignia — operar cuentas de Cloudflare, para sus propios productos y para sus clientes, es parte de lo que Ignia hace. Math Challenge es un proyecto de Ignia, patrocinado por Ignia.

Cloudflare provee la plataforma. Workers, D1, KV, R2, Analytics Engine y la red sobre la que corren son productos de Cloudflare, operados por Cloudflare. Ignia opera; Cloudflare provee. Dos verbos, dos empresas, separados a propósito — y la razón de separarlos es la misma sobre la que está armada toda esta página: el lector de una página de arquitectura es el que comprueba.

Una de esas dos mitades está a una consulta pública de DNS. Leída en la fecha de arriba:

dig +short NS math.kilowatto.com
alberto.ns.cloudflare.com.
colette.ns.cloudflare.com.

La otra mitad no se puede consultar en ningún lado, y lo decimos. Que este dominio lo sirva Cloudflare cualquiera lo confirma. Que Ignia opere la cuenta es una afirmación nuestra: no hay registro público donde ir a comprobarla. Decirlo así vale más que adornarlo, porque basta una sola afirmación que no se pueda comprobar para que el lector deje de comprobar las demás.

Lo que esta página no afirma, a propósito: que Ignia sea partner de Cloudflare. No nombramos ningún nivel de partner ni enseñamos ninguna insignia, porque no hay directorio público donde pudieras verificarlo. En una página cuya promesa entera es «y así se comprueba», una afirmación que no se puede comprobar cuesta más de lo que vale.

Ignia, en sus propias palabras: ignia.cloud

Cómo comprobar cualquiera de estas cosas

el anuncio de HTTP/3 en las cabeceras de respuesta
curl -sI https://math.kilowatto.com/en/ | grep alt-svc
0-RTT: el ticket de sesión de TLS 1.3 y su permiso de datos tempranos
openssl s_client -connect math.kilowatto.com:443 -tls1_3 -sess_out s.pem
openssl sess_id -in s.pem -text | grep "Max Early Data"
el camino de RPC: primer Worker, segundo Worker, D1
curl -s https://math.kilowatto.com/api/health
los pesos citados arriba, desde el repositorio
node audits/bundle-budget.mjs

Fuentes

  1. About Service bindings — Cloudflare Workers docs
  2. We've added JavaScript-native RPC to Cloudflare Workers
  3. Support HTTP/2 bidirectional streaming (gRPC) in Workers/Durable Objects — cloudflare/workerd issue #6455
  4. gRPC Web (PROTOCOL-WEB) — gRPC core documentation
  5. Road to gRPC — Cloudflare blog
  6. HTTP/3 (with QUIC) — Cloudflare Speed docs
  7. D1 Platform limits — Cloudflare docs
  8. JSON Mode — Cloudflare Workers AI docs

Math Challenge es un proyecto de Ignia, y corre sobre Cloudflare. Son dos afirmaciones y se mantienen separadas a propósito: decir que Ignia provee el stack sería desmentible con una sola consulta de DNS, y el lector de una página de arquitectura es exactamente quien la haría. ignia.cloud