Vista generada de dec-0115: TypeBox sustituye a Arktype en los contratos contract-first
docs/decisions/dec-0115-typebox-sustituye-arktype.mdVista generada desde
docs/decisions/dec-0115-typebox-sustituye-arktype.md. No se edita a mano:bun run docs:genla regenera ybun run docs:checkfalla si difiere. El estado aquí es el del model: si discrepa con otra página, manda el model.
| Campo | Valor |
|---|---|
| Estado | SUPERSEDED |
| Fecha | 2026-09-28 |
| Fichero | docs/decisions/dec-0115-typebox-sustituye-arktype.md |
Enmienda a: r18, r20
Enmendado o sustituido por: dec-0116
Por qué importa (del frontmatter del ADR):
Decide la librería de los wire contracts contract-first de
@styx/api-contractsy@styx/domain(r20 §2.3). La validan en runtime todos los svcs NATS y el transport HTTP de playback-svc, y la librería se carga en cada contenedor (r17).
Nodos del roadmap que lo citan en refs: ninguno.
Páginas de la documentación que lo citan: ninguna todavía.
Leído de docs/decisions/dec-0115-typebox-sustituye-arktype.md, el fichero canónico.
@styx/api-contracts, no se derivan de Elysia).spikes/typebox-vs-arktype/RESULTS.md + data/*.json (rama
bench/typebox-vs-arktype, base bb1d967).r18/r20 fijaron Arktype como librería contract-first. spire ya usa TypeBox (el t.* de
Elysia). waxin pidió decidir con datos. El spike porta 1:1 un subconjunto real de 17 schemas
(MessageEnvelope<T>, Work/Edition/MediaAsset/SourceBinding, PlaybackPlan con unions
discriminadas, TransportSignalsSnapshot, identity, errores tipados). Los 6 engines tienen
paridad verificada (0 divergencias en bun y node) y la inferencia se verifica con tsgo y un
control mutante.
| eje | arktype 2.2.5 | typebox 1.3.34 | @sinclair/typebox 0.34.52 |
|---|---|---|---|
| heap total bun / node | 17.95 / 19.62 MB | 3.17 / 6.59 MB | 2.16 / 2.82 MB |
| cold start lib bun / node | 323 / 433 ms | 123 / 205 ms | 50 / 94 ms |
| bundle web gzip | 47 KB | 34 KB | 23 KB |
| tsgo check / memoria | 151 ms / 43 MB | 69 ms / 29 MB | 60 ms / 21 MB |
| mix válido ops/s bun / node | 4.25M / 3.69M | 6.30M / 3.50M | 4.54M / 4.82M |
| mix 90/10 con errores detallados | 520k / 500k | 156k / 153k | 794k / 720k |
La condición se cumple: TypeBox consume menos en heap, cold start, bundle y typecheck, y empata o gana en CPU en el camino válido. Pierde en el camino de error con TypeBox 1.x (≈ 3.3× más lento) y en la calidad de los mensajes de error en unions.
@styx/api-contracts y @styx/domain. Los contratos pasan a TypeBox,
validados con el validador compilado (Compile / TypeCompiler). El modo Value.*
sin compilar es 10–270× más lento y queda prohibido en hot paths.typebox 1.x, la vigente en npm y la única que acepta Elysia 2.0. @sinclair/ typebox 0.34 consume aún menos, pero es la línea anterior. Sólo se acepta como puente
mientras el repo siga en Elysia 1.4, que no acepta TypeBox 1.x (verificado: 500 en
runtime)..toJsonSchema(), que hoy
falla con el .narrow() de SourceBinding.preference.@styx/api-contracts y @styx/domain/models, los
sitios de validación listados en RESULTS.md §Inventario y parseEnvelope. El genérico
MessageEnvelope<T> pasa a ser EnvelopeOf<T extends TSchema>(t).Expected union value sin ruta. Mitigación: formatear los errores en
parseEnvelope (primer error por ruta más profunda).Check booleano y
materializar Errors sólo para el log (con rate-limit).apps/web arrastra hoy la librería de validación entera
por el barrel de @styx/api-contracts (createRequestId). Hay que importar el módulo hoja.Value.Check): gana en memoria y cold start, pero es 10–200× más
lento en validación.