Coste de una pasada
Medido el 2026-09-11 con el binario real contra la API viva, con todas las
familias encendidas y cada petición registrada con las cabeceras
x-ratelimit-resource y x-ratelimit-used de su propia respuesta. Frío es
la primera pasada de una instalación nueva: caché de ETag vacía, un mes de
ejecuciones de workflows. Un servicio reiniciado ya no empieza ahí: vuelve a
leer su caché del fichero junto al fichero de
estado, y solo uno
que haya perdido ese fichero vuelve a pagar la caché vacía. Estable es la
tercera pasada del mismo proceso unos minutos después, cuando cuatro quintas
partes de sus peticiones se respondieron con 304 y no costaron nada; la segunda
pasada es la que paga la puesta al día que describe la fila de actions. Un 304 es
gratis, y solo existe para REST: GraphQL no lleva ETag, así que su columna es la
misma en las dos pasadas.
Las cifras son por repositorio donde la familia pregunta por repositorio, y por
pasada donde pregunta por la cuenta. core es el cubo de REST, pt un punto
de GraphQL. Las familias con alguna petición que no es core dicen a qué cubo
fue: search (30 por minuto), webhook_deliveries (500 por minuto) y
dependency_sbom (100 por minuto) tienen cada uno el suyo. Una fila que la
ronda del 2026-09-11 cambió describe las peticiones que el código hace ahora y
dice qué midieron las dos pasadas donde difiere. No hay fila de total a
propósito: un total pertenece a una cuenta y envejece con ella, así que
multiplica las filas por repositorio por los repositorios que imprime -list y
tendrás el tuyo.
Por familia
Sección titulada «Por familia»| Familia | Cadencia | Frío | Estable | Notas |
|---|---|---|---|---|
| account | 1h | 1 pt, 7 core | 1 pt, 1 core | una consulta: el calendario, los totales, los pins, el bloque de sponsors y las listas de estrellas; 66 KB, nunca comprimida, nunca condicional; a su lado el perfil, por las organizaciones que el following de GraphQL deja fuera, que GitHub casi nunca respondió con un 304, una vez en 48 lecturas condicionales del 2026-09-12 al 2026-09-27, y los seis listados de paquetes que GraphQL no ve, que lo responden hasta que cambia un paquete |
| achievements | 1h | 1 página fuera de presupuesto, 1 pt, más el recorrido de coautoría | 1 página fuera de presupuesto, 2 pt | las insignias salen de la página pública del perfil, leída sin el token y sin cargarse a ningún cubo. Las filas de progreso de al lado sí salen de la API: una consulta de cuentas, y un recorrido por las pull requests fusionadas cuyos commits en coautoría no expone ninguna cuenta. La primera pasada recorre la vida entera de la cuenta, y como la búsqueda se detiene a los mil resultados parte en dos cualquier rango que se pase, un punto por página y uno por partición, y uno por consulta que sigue leyendo más allá de los cien primeros commits de una pull request que tiene más, diez pull requests por consulta, que son decenas de puntos en una cuenta antigua y uno en una nueva: 35 consultas y 23,7 MB sobre 2.315 pull requests públicas fusionadas, medido el 2026-09-27. El recuento que encuentra se guarda en el fichero de estado con el día que cubre, así que cada pasada posterior recorre solo las pull requests fusionadas desde entonces, una página, de 468 a 513 KB en cada pasada horaria que registró el proxy de producción el 2026-09-27 en la misma cuenta, un tamaño que crece a lo largo del día con lo que se fusiona, donde el recorrido entero había sido de 18 a 24 MB cada día; el historial entero se vuelve a recorrer una vez por semana, porque un repositorio que pasa a privado o se borra saca sus pull requests del recuento. La página y los dos puntos cada hora, el recorrido entero una vez por semana |
| totals | 1h | 1 search, 1 pt, más 1 pt por cada 10 repos y 1 por cada 25 archivados que se dejan fuera | igual | diez de los once contadores son una consulta GraphQL de diez alias, 406 bytes a coste 1, medida idéntica a las respuestas REST del mismo minuto; solo el contador de commits sigue siendo una búsqueda, cobrada cada vez; una consulta de contadores rechazada se repite contador a contador, diez puntos solo en esa pasada, así que una búsqueda fallida pierde un número, como en REST |
| ratelimit | 15m | 1 pt | 1 pt | GET /rate_limit es gratis; el punto es la mitad GraphQL de la misma pregunta |
| events | 15m | 3 core | 1 core | antes de la ronda: tres páginas de un feed que cambia cada vez, así que If-None-Match nunca acierta. Ahora: el recorrido se detiene en la página que lleva el evento más reciente de la pasada anterior, recordado como last_event en el fichero de estado, que suele ser la primera página: 1 core por pasada, 192 al día menos al cuarto de hora; una primera pasada y un backfill siguen leyendo las tres |
| notifs | 15m | 20 core | 1 core | antes de la ronda: veinte páginas de cincuenta; una notificación nueva desplaza todas las páginas, así que el ETag nunca acierta, para seis o siete filas nuevas. Ahora: since= el updated_at más reciente visto menos dos cadencias (last_notified en el fichero de estado), que al cuarto de hora es una página para una ventana que se abre media hora antes del hilo más reciente visto: 1 core por pasada, y las veinte una vez al día (last_full), en un backfill y en la primera pasada tras una actualización, hilos leídos incluidos (all=true): eso acota a un día lo que el filtro de GitHub haya dejado fuera de las lecturas con ventana, y es la lectura que cierra un hilo, porque una pasada lista solo los hilos no leídos y un hilo leído sin respuesta desaparece de ese listado en vez de volver con su etiqueta unread cambiada. unos 1.800 core al día menos al cuarto de hora |
| billing | 1h | 2 core | 1 core | una por mes recorrido; el mes en curso cambia, el anterior es un 304. Medido del 2026-09-13 al 2026-09-26, cada seis horas, el mes en curso respondió 200 a las 46 lecturas condicionales y el anterior 304 a las 46 |
| profile | 12h | 4 core más 1 por paquete | 0 core | el perfil, las cuentas sociales, los gists, los paquetes y una página de versiones por paquete; todo 304 tras la primera pasada |
| outbound | 1h | 9 pt, más 1 por cada cien más de estrellas dadas, de elementos abiertos o movidos desde la pasada anterior, o de respuestas aceptadas | lo mismo | todo GraphQL: la lista de estrellas dadas es una consulta de cien por página (13,5 KB frente a 617 KB descomprimidos por REST), de la más nueva a la más antigua, hasta cinco páginas en cada pasada y todas en un backfill, las cinco búsquedas un punto por página (7 KB frente a 100 KB), los dos recorridos de comentarios uno cada uno, y las respuestas aceptadas de la cuenta uno más, leídas aparte para que una respuesta aceptada cuando su comentario ya había salido de los cien más recientes se siga escribiendo (eran 15 el 2026-09-26, una página, y cinco páginas como mucho en una pasada). Las dos búsquedas de lo que sigue abierto se leen hasta el final en cada pasada, una página mientras la cuenta no tenga más de cien abiertos de un tipo, y las tres de lo fusionado o cerrado hasta una cadencia antes de la pasada anterior, ordenadas por lo que se movió último, lo que es una página cada una salvo que se hayan movido más de cien en ese tiempo; un backfill lee también esas hasta el final, diez páginas como mucho, porque la búsqueda sirve mil resultados y ni uno más. Nada de esto lleva ETag por ninguna de las dos vías, así que las dos columnas son iguales |
| history | apagada | 1 pt por año pasado | igual | el calendario entero de la cuenta, una vez, a un punto por año que lleve existiendo |
| keys | 24h | 2 core | 0 core | las claves SSH y GPG |
| traffic | 6h | 4 core por repo | 0 core | visitas, clones, referrers, rutas; la ventana de catorce días es un 304 hasta que se mueve |
| repo | 1h | 3 core por repo, 2 pt por cada 10 repos | 0 core en un repo que no cambió, 2 pt por cada 10 repos | el repositorio, su perfil de comunidad y una página de releases cada uno; lenguajes, temas, rulesets y protección de rama viajan en una consulta GraphQL por cada diez repositorios. Un fork no tiene perfil de comunidad, y el 404 con el que responde, que se cobra entero porque no lleva ETag, se pregunta una vez al día y no en cada pasada: a quince forks se les cobraron 404 en 30,9 horas, y con la memoria se les cobran 15 al día |
| branches | 24h | 1 pt por cada 14 repos | 1 pt por cada 14 repos | una consulta por cada catorce repositorios |
| stars | 1h | 1 core por repo, más 1 core por cada 30 semanas de su vida | 1 pt por cada 10 repos, más 1 core por repo, casi siempre un 304 gratis | el recorrido completo por REST la primera vez que se ve un repositorio, y después las cien estrellas más nuevas de cada repositorio en una consulta GraphQL por cada diez, alrededor de un kilobyte por repositorio; un reinicio con fichero de estado empieza en esa consulta. Antes de la ronda se pedía la última página de cada repositorio en cada pasada, todas menos una con 304. El historial diario de estrellas llegó después de la ronda y no está en sus cifras: 1 core por repositorio, un 304 salvo que un día de las últimas treinta semanas ganara o perdiera una estrella o empezara una semana; su primera lectura es una página por cada treinta semanas de vida del repositorio, 180 páginas para los diecinueve repositorios con estrellas de la cuenta medida, una vez |
| issues | 1h | hasta 4 pt por página de un mes de movimientos, 1 pt o más por abiertos | 1 a 2 pt por repo que se movió | antes de la ronda: una página de cincuenta con diez hilos de revisión cada uno, 8 puntos, que el gateway rechazaba con un 502 una vez por pasada en el repositorio más activo. Ahora: 2 puntos de GraphQL por repo para lo que cambió en dos cadencias, de diez en diez (1 punto donde el repositorio tiene cinco o menos). La primera pasada de cada día UTC lee además cada elemento abierto de cada repositorio, por mucho que haga que se movió, en páginas dimensionadas desde los recuentos de abiertos de los últimos totales, y lo que se movió desde la lectura del día anterior, un mes atrás con un fichero de estado nuevo, en páginas de hasta veinticinco (5, 10, 20, 25 o 50 cuestan 1, 2, 3, 4 o 9, preguntado con dryRun el 2026-09-30). Hasta la 2.6.5 la lectura del día era una página de los cincuenta elementos de cualquier estado actualizados por último, que perdía un elemento abierto en cuanto otros cincuenta se movían después, y chocaba con los diez segundos del gateway en el repositorio más activo cada día. Desde la 2.6.0, la lectura de lo que cambió solo pregunta a los repositorios donde se actualizó una issue o una pull request en su ventana, que antes dice una sola consulta para todos ellos (ver Preguntar primero qué se movió); la lectura de cada elemento abierto se hace en todos los repositorios |
| issueevents | 1h | varios pt por repo actualizado en el mes, más 1 core por pull request en pila | 1 pt por repo que se movió, 0 a 1 core | antes de la ronda: una página de cien eventos cada uno, hasta un megabyte por repositorio porque cada evento incrusta su issue entera; un 304 en todos menos el repositorio que se movió. Ahora: una consulta GraphQL por repositorio, la cronología de las diez issues y diez pull requests actualizadas más recientemente para los eventos de las dos últimas cadencias (1 pt, de 2 a 6 KB, una segunda página solo cuando se movieron más de diez), más un core por pull request en una pila, cuyo evento added_to_stack la cronología no sabe nombrar; treinta días en una primera pasada, una vez, que son minutos y no segundos donde las pull requests están casi todas en pila, porque casi todas las actualizadas en el mes van por la vía por ítem a por su added_to_stack; una pasada estable es un punto por repositorio que se movió y como mucho una lectura de esas. Y desde una cadencia antes de la última ejecución tras un hueco, para que un proceso parado no deje sus horas fuera de la serie. Medido contra la lista durante una semana de dos repositorios: todos los eventos de todos los tipos coinciden, campo a campo, salvo un commit que referencia una issue que nadie ha tocado, 3 de 2.217, que no mueve la issue y por eso no se pregunta. Un backfill recorre /issues/{n}/events por ítem en vez de la lista, 1,4 KB comprimidos por doce eventos frente a 45 KB por evento. Desde la 2.6.0, una pasada solo pregunta a los repositorios donde se actualizó una issue o una pull request en su ventana (ver Preguntar primero qué se movió) |
| actions | 15m | un mes de ejecuciones por repo, más 1 core por ejecución | 1 core por repo que tuvo una ejecución, más 1 por ejecución terminada desde entonces | antes de la ronda: páginas de cien ejecuciones hasta un mes atrás, un listado de jobs por ejecución, y las cachés y workflows de cada repositorio, que eran tres quintas partes de los bytes de la pasada fría, y esos listados de jobs otra vez en cada pasada, casi todos 304. Ahora: páginas de 30, una en un repositorio tranquilo y hasta 7 mientras vengan llenas de ejecuciones más nuevas que la ventana, más una por ejecución aún sin expandir, jobs listados una vez por intento, como mucho 20 ejecuciones nuevas por pasada; páginas de 100 en la primera pasada y en un backfill. Medido en tres pasadas de un mismo proceso, la segunda es la que paga la puesta al día, porque la página de treinta es una URL nueva para cada repositorio y trae ejecuciones que las veinte de la primera no cubrieron; desde ahí una pasada cuesta una página por repositorio que tuvo una ejecución y un listado de jobs por ejecución terminada desde entonces, así que lo que cuesta es cuántas ejecuciones termina la cuenta. El listado de cachés se lee en páginas de cien entradas, hasta diez, así que solo un repositorio de más de cien paga una segunda, y una página es un 304 mientras el listado no cambia: del 2026-09-25 12:58Z al 2026-09-27 01:39Z los listados de la cuenta respondieron 304 a 3.059 de 3.256 peticiones |
| artifacts | 1h | hasta 5 core por repo | 0 a 5 core por repo | un repositorio activo llena sus páginas, y las cinco se cobran otra vez cada vez que se añadió o caducó un artefacto: 5 en una pasada, 0 en la siguiente |
| security | 1h | 2 core por repo | 0 core | alertas de Dependabot y de code scanning; la mayoría son el 403 de un repositorio con Dependabot apagado o el 404 de uno sin code scanning, y un rechazo no lleva ETag, así que cada uno se volvía a cobrar en cada pasada antes de que la ronda los recordara. Ahora: un rechazo se contesta de memoria durante un día, por familia, repositorio y endpoint, así que la cifra estable es 0 core en la segunda pasada y una petición por rechazo una vez al día. El resto son peticiones condicionales, todas 304. Solo una lista cuya primera página vuelve llena, en un repositorio con más de cien alertas de ese tipo, pide más: sus alertas abiertas, una página por cada cien que sigan abiertas, y en code scanning una página de una sola alerta cuya última página es el total. Medido el 2026-09-26 son dos listas de esta cuenta y tres peticiones por pasada, condicionales como el resto y un 304 mientras nada se mueve |
| stats | 12h | 3 core por repo | 0 core | participación y punch card; GitHub los recalcula despacio y responde 304 |
| discussions | 1h | 2 pt por repo con foro | igual | antes de la ronda: cincuenta hilos con veinte comentarios y veinte respuestas cada uno, 11 puntos, pedidos a todos los repositorios, incluidos todos los que no tienen foro. Ahora: 2 puntos por repo con foro, los diez hilos actualizados más recientemente con los mismos veinte comentarios y veinte respuestas cada uno (los comentarios llegan del más antiguo al más nuevo, así que una página más corta ahí dejaría de registrar el undécimo comentario de un hilo); un repositorio con el foro apagado no se consulta |
| commits | 1h | 1 pt por repo con un commit en el mes | 1 pt por repo que se movió | las dos últimas cadencias de la rama por defecto, desde la 2.6.0 solo en los repositorios cuya cabeza tiene el commit dentro de ellas (ver Preguntar primero qué se movió); un mes atrás en la primera pasada, que son unos cientos de kilobytes para un repositorio activo; donde la pasarela se rinde con esa página de cincuenta, como hizo en el repositorio más activo medido, se lee en páginas de veinticinco |
| activity | 15m | 2 core por repo | 0 a 2 core por repo | el log del repositorio, cien entradas por página; se cobra solo en un repositorio cuyo log se movió, 2 en una pasada y 0 en la siguiente |
| analyses | 1h | 1 core por repo | 0 core | la mayoría son el 403 y el 404 de repositorios sin code scanning, cobrados otra vez en cada pasada antes de la ronda; ahora recordados un día, así que la pasada estable son peticiones condicionales y 0 core |
| forks | 12h | 1 core por repo | 1 pt por cada 10 repos | una página cada uno por REST en la primera pasada de una instalación nueva y en un backfill, y después los cien forks más nuevos de cada repositorio en una consulta GraphQL por cada diez, menos de un kilobyte por repositorio; un repositorio del que el lote informa que tiene más de cien forks se recorre también por REST, porque las estrellas y el último empujón de una fila de fork cambian y el lote no puede refrescar las filas más allá de su página. Antes de la ronda: una petición por repositorio y pasada, todas 304 |
| planning | 6h | 1 pt por repo | 1 pt por repo | etiquetas e hitos |
| joblogs | apagada | 1 core por repo, 1 blob por job fallido | 0 core | las ejecuciones fallidas de la última hora por repositorio, pedidas a una lista filtrada al mes al que puede llegar una reejecución, y un blob por job fallido desde el almacenamiento de objetos, fuera de la cuota de la API; la URL del filtro cambia una vez al día, así que un día cuesta una página cobrada por repositorio y el resto son 304 |
| settings | 6h | 2 core por repo, 1 webhook_deliveries por hook | 0 core, 1 webhook_deliveries por hook que se movió | webhooks, entornos y claves de despliegue; las entregas de cada hook se cobran a su propio cubo |
| rulesets | 24h | 1 core por repo más 1 por ruleset | 0 core | un listado por repositorio y un historial por ruleset, los dos con ETag; nada de eso se cobra un día en que nadie editó un ruleset, cuando la pasada estable hace las mismas preguntas y todas son condicionales |
| inventory | 24h | 4 core por repo | 0 core | la política del token de workflow, los secretos, la configuración de code scanning; los rechazos eran el 403 de los repositorios sin ella, ahora recordados un día, que a esta cadencia es la pasada siguiente de todos modos; el resto son peticiones condicionales, todas 304 |
| deployments | 30m | 1 pt por cada 5 repos | 1 pt por cada 5 repos | una consulta por cada cinco repositorios, los cien despliegues más recientes de cada uno |
| policyfiles | 24h | 1 pt por cada 5 repos | 1 pt por cada 5 repos | una consulta por cada cinco repositorios, el historial de cuatro rutas de cada uno |
| deps | apagada | 1 core y 1 dependency_sbom por repo | 0 core, 1 dependency_sbom por repo que recibió un commit | una lectura de commit y un SBOM por repositorio; el SBOM tiene su propio cubo y la mayoría fueron 404, ahora recordados un día. GitHub regenera el SBOM en cada lectura y su ETag nunca acierta, así que la fotografía solo se toma cuando la cabeza se movió desde la última pasada (la cabeza en sí es un 304 gratis cuando no lo hizo): 0 dependency_sbom en un repositorio sin commit, uno por repositorio que lo recibió, y una de las lecturas de SBOM expiró en el lado de GitHub en cada una de las tres pasadas medidas |
Lo que pesaba antes de la ronda no era REST sino GraphQL: issues y
discussions eran el 88 % de los puntos, porque las dos consultas estaban
dimensionadas para un backfill y se pedían en cada pasada. La única búsqueda
es el contador de commits de totals, una por pasada contra un presupuesto de
treinta por minuto.
La ronda del 2026-09-11 rebajó varias de estas filas, y la primera medida es
la base contra la que se mide: los listados de jobs de una
ejecución ya expandida no se vuelven a pedir, la página de ejecuciones es de
treinta en una pasada ordinaria, discussions solo se pregunta a los
repositorios con foro y por diez hilos, pulls se dimensiona al repositorio y
se acota a dos cadencias, las notificaciones y el feed de eventos se detienen
en lo que vio la pasada anterior, un 403 o 404 se recuerda un día en vez de
cobrarse otra vez cada hora, y las estrellas y forks más nuevos, la lista de
estrellas dadas, las búsquedas de outbound y diez de los once contadores de
totals pasaron de REST a GraphQL, las mismas filas por un punto cada una en
vez de una petición cada una. Medido otra vez después de la ronda, tres
pasadas de un mismo proceso la tarde del mismo día, la pasada estable cobra
alrededor de un tercio del core y un tercio de los puntos de GraphQL que
cobraba antes, mueve la mitad de los bytes por el cable y responde con 304 unas
cuatro quintas partes de sus peticiones. Proyectado a un día a las cadencias de
entonces, eso es más o menos una octava parte de las llamadas REST y un tercio
de los puntos, más un listado de jobs por ejecución de workflow terminada, que
es el único término que crece con lo activos que sean los repositorios y no con
cuántos haya. Dos cosas no bajaron. La pasada fría cobra más core que antes,
porque la primera pasada de eventos de issue lee ahora el mes entero por la
cronología y, donde las pull requests están en pila, una lista por ítem para
casi cada pull request actualizada en él: minutos, una vez por proceso. Y una
pasada que ejecuta todas las familias a la vez sigue tardando minutos y no
segundos, porque sus peticiones condicionales cuestan un tercio de segundo cada
una y sus consultas GraphQL nueve décimas, una tras otra; las pasadas que hace
producción son la de 15 minutos y la de cada hora, cada una una fracción del
total.
Las cadencias de la 2.6.0 ejecutan diez familias más a menudo, events,
notifs y activity cada cuarto de hora, deployments cada media hora, y
stars, billing, analyses, account, totals y discussions cada hora,
porque sus pasadas de más no cuestan casi nada. Costeadas con el registro de
peticiones del proceso de producción del 2026-09-25 a las 12:58Z al 2026-09-26 a
las 19:50Z, 37 repositorios, dejando fuera la primera pasada de cada familia
para que toda pasada contada tuviera la caché de ETag caliente, añaden unas 250
peticiones core y 500 puntos de GraphQL al día, el 0,2 y el 0,4 % de los dos
presupuestos diarios, y 22 peticiones de búsqueda. Los puntos son sobre todo
deployments, ocho por pasada allí, y totals, seis; las peticiones core,
sobre todo activity, events y analyses, que solo se cobran por lo que se
movió, porque un 304 es gratis: en el mismo registro, una petición core
respondida con 304 dejó x-ratelimit-used donde lo había puesto la anterior de
la misma ventana 11.692 veces de 11.771. Otras dos familias corren cada hora
desde la misma versión, cada una con su precio en su fila de arriba:
outbound, que corría cada doce, y achievements, que corría una vez al día
mientras cada pasada recorría el historial entero de fusiones.
Preguntar primero qué se movió
Sección titulada «Preguntar primero qué se movió»commits, issueevents y la pasada incremental de issues solo leen lo que
se movió desde una ventana propia, una consulta GraphQL por repositorio, y
GitHub cobra una consulta por la página que pide, no por lo que vuelve. Así que
una pasada que ejecuta cualquiera de las tres pregunta primero a cada
repositorio, veinticinco por consulta a un punto cada una, cuándo se hizo el
commit de la cabeza de su rama por defecto y cuándo se actualizaron su issue y
su pull request más recientes, y cada familia deja sin leer un repositorio donde
nada se movió desde el inicio de su propia ventana. Es la condición en la que
la lectura vuelve vacía, no una estimación de ella: medido el 2026-09-27,
history(since:) contiene una cabeza cuyo commit es del mismo segundo que
nombra y nada un segundo después. Un repositorio para el que la consulta no
responde se lee como siempre, y ni la lectura diaria de cada elemento abierto de
issues ni un backfill la hacen.
Ninguna fila de la tabla de arriba lleva la consulta, porque no pertenece a
ninguna de las tres: es un punto por cada veinticinco repositorios en cada
pasada que ejecuta alguna de ellas. Una familia que deja repositorios sin leer
dice cuántos, una vez por pasada, y su fila de
gh_collector_family
los cuenta en repos junto a los que leyó, sin escribir filas por ellos:
level=INFO msg="nothing moved since the window, repositories left unread" family=commits repos=34Una consulta que falló, o que respondió por unos repositorios y no por los demás, se dice con un aviso, y cada repositorio del que no dio respuesta se lee como si no se hubiera preguntado:
level=WARN msg="which repositories moved could not be asked, reading those it did not answer for" answered=36 repos=37 err="graphql: the gateway gave up (502); the query is too large for one request (36 repositories were asked successfully)"Del registro de peticiones del proceso de producción entre el 2026-09-25 a las
12:58Z y el 2026-09-26 a las 19:50Z, 27 pasadas de cada familia sobre 37
repositorios, antes de que existiera la consulta: 961 de las 999 respuestas de
commits no traían ningún commit, y 468 de las 968 respuestas incrementales de
issues y 486 de las 1.005 de issueevents no traían ningún ítem, 2.077
puntos en total, el 43 % de los 4.786 que el proceso gastó en GraphQL. Para esos
37 repositorios la consulta cuesta dos puntos por pasada, 54 en las 27 pasadas,
así que ahorra 2.023 puntos, unos 66 por hora: el 42 % de todos los puntos de
GraphQL y el 52 % de los de las tres familias. Es un mínimo. Una respuesta
cuenta como vacía cuando pesa menos de 300 bytes, el bloque del presupuesto y
una lista vacía; un repositorio cuyas issues y pull requests son todas
anteriores a la ventana responde igualmente con una página de ellas, no se
cuenta aquí, y se salta igual.
GraphQL es el barato, por mucho
Sección titulada «GraphQL es el barato, por mucho»Una consulta devuelve el calendario de contribuciones completo de 366 días, todos los totales de contribución, el desglose de commits por repositorio y las cuentas sociales, por un punto de un presupuesto de cinco mil. Lo mismo por REST serían docenas de llamadas y no incluiría el calendario en absoluto, porque el calendario no existe en ningún otro sitio.
Por eso la familia de cuenta puede correr cada hora y aun así no costar casi nada, y por eso las familias caras son las de REST que crecen con lo activos que estén los repositorios.
Qué crece con la actividad, no con el tamaño
Sección titulada «Qué crece con la actividad, no con el tamaño»Todo lo demás cuesta un número de llamadas más o menos fijo por repositorio. Esto no:
actionscuesta una página de treinta ejecuciones, hasta siete mientras vengan llenas de ejecuciones más nuevas que la ventana, más una petición por cada ejecución cuyos jobs este proceso aún no ha escrito, como mucho veinte por pasada. Un repositorio con integración continua en cada push genera ejecuciones sin parar; uno tranquilo cuesta esa página, contestada con 304, y nada más.artifactsrecorre hasta cinco páginas por repositorio, y un repositorio activo las llena y se las vuelve a cobrar cada vez que se añadió o caducó un artefacto.activitysolo se cobra en un repositorio cuyo log se movió: la página de uno que no se movió es un 304 gratis.commits,issueeventsy la pasada incremental deissuessolo leen los repositorios donde algo se movió en su ventana, un punto o dos cada uno, después de preguntar cuáles por un punto por cada veinticinco repositorios. La lectura diaria de cada elemento abierto deissuesse hace en todos los repositorios, activos o no.outboundcuesta un punto más por cada cien más de lo que lee: estrellas dadas, elementos abiertos o movidos desde la pasada anterior y respuestas aceptadas.
Apagar una familia
Sección titulada «Apagar una familia»Pon su intervalo a 0.
every: families: artifacts: 0 joblogs: 0Una familia apagada no escribe nada y no cuesta nada. Sus paneles del dashboard se quedan vacíos, que es la lectura honesta. Ver cadencias.
Hacer la cuenta para tu propia cuenta
Sección titulada «Hacer la cuenta para tu propia cuenta»La primera pasada es la cara: el recorrido completo de estrellas, el historial
diario de estrellas entero de cada repositorio, un mes de ejecuciones de
workflows, las pull requests en coautoría de toda la vida de la cuenta, que
achievements vuelve a recorrer una vez por semana (35 consultas y 23,7 MB
sobre 2.315 pull requests públicas fusionadas, medido el 2026-09-27), y, con
every.families.history puesto, el calendario de contribuciones de cada año
pasado. Después, multiplica las filas por repositorio de arriba por el número
de repositorios que imprime -list, y divide el presupuesto por hora entre la
cadencia.
Una tarjeta ejecuta todas las familias digan lo que
digan las cadencias, porque cada número que dibuja sale de esa única pasada,
así que N tarjetas son N pasadas, y un workflow que dibuja tres paga tres. Su
GraphQL es el de una pasada entera cada vez, porque GraphQL no lleva ETag. Sus
peticiones REST son las de la columna en frío solo la primera vez: toda
ejecución lee el fichero de caché que hay junto a su state_file y pregunta
con los validadores guardados allí, así que desde la segunda tarjeta una página
que no cambió es un 304 gratis. Una ejecución cuyo fichero de estado no se
conserva de una ejecución a la siguiente las paga en frío cada vez: un
contenedor sin nada montado donde va el fichero, o la Action sin config:, que
empieza cada ejecución con un directorio de estado propio. Una ejecución
-card-only lee el fichero de caché y nunca lo escribe, así que solo va en
caliente cuando otra ejecución mantiene ese fichero.
La señal de que la suma salió mal es un aviso, no una conjetura:
level=WARN msg="rate limit reserve reached, family skipped" family=actionsDe vez en cuando está bien. En cada pasada significa que las cadencias son demasiado rápidas para el número de repositorios.