Ir al contenido

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.

FamiliaCadenciaFríoEstableNotas
account1h1 pt, 7 core1 pt, 1 coreuna 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
achievements1h1 página fuera de presupuesto, 1 pt, más el recorrido de coautoría1 página fuera de presupuesto, 2 ptlas 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
totals1h1 search, 1 pt, más 1 pt por cada 10 repos y 1 por cada 25 archivados que se dejan fueraigualdiez 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
ratelimit15m1 pt1 ptGET /rate_limit es gratis; el punto es la mitad GraphQL de la misma pregunta
events15m3 core1 coreantes 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
notifs15m20 core1 coreantes 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
billing1h2 core1 coreuna 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
profile12h4 core más 1 por paquete0 coreel perfil, las cuentas sociales, los gists, los paquetes y una página de versiones por paquete; todo 304 tras la primera pasada
outbound1h9 pt, más 1 por cada cien más de estrellas dadas, de elementos abiertos o movidos desde la pasada anterior, o de respuestas aceptadaslo mismotodo 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
historyapagada1 pt por año pasadoigualel calendario entero de la cuenta, una vez, a un punto por año que lleve existiendo
keys24h2 core0 corelas claves SSH y GPG
traffic6h4 core por repo0 corevisitas, clones, referrers, rutas; la ventana de catorce días es un 304 hasta que se mueve
repo1h3 core por repo, 2 pt por cada 10 repos0 core en un repo que no cambió, 2 pt por cada 10 reposel 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
branches24h1 pt por cada 14 repos1 pt por cada 14 reposuna consulta por cada catorce repositorios
stars1h1 core por repo, más 1 core por cada 30 semanas de su vida1 pt por cada 10 repos, más 1 core por repo, casi siempre un 304 gratisel 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
issues1hhasta 4 pt por página de un mes de movimientos, 1 pt o más por abiertos1 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
issueevents1hvarios pt por repo actualizado en el mes, más 1 core por pull request en pila1 pt por repo que se movió, 0 a 1 coreantes 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ó)
actions15mun mes de ejecuciones por repo, más 1 core por ejecución1 core por repo que tuvo una ejecución, más 1 por ejecución terminada desde entoncesantes 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
artifacts1hhasta 5 core por repo0 a 5 core por repoun 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
security1h2 core por repo0 corealertas 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
stats12h3 core por repo0 coreparticipación y punch card; GitHub los recalcula despacio y responde 304
discussions1h2 pt por repo con foroigualantes 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
commits1h1 pt por repo con un commit en el mes1 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
activity15m2 core por repo0 a 2 core por repoel 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
analyses1h1 core por repo0 corela 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
forks12h1 core por repo1 pt por cada 10 reposuna 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
planning6h1 pt por repo1 pt por repoetiquetas e hitos
joblogsapagada1 core por repo, 1 blob por job fallido0 corelas 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
settings6h2 core por repo, 1 webhook_deliveries por hook0 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
rulesets24h1 core por repo más 1 por ruleset0 coreun 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
inventory24h4 core por repo0 corela 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
deployments30m1 pt por cada 5 repos1 pt por cada 5 reposuna consulta por cada cinco repositorios, los cien despliegues más recientes de cada uno
policyfiles24h1 pt por cada 5 repos1 pt por cada 5 reposuna consulta por cada cinco repositorios, el historial de cuatro rutas de cada uno
depsapagada1 core y 1 dependency_sbom por repo0 core, 1 dependency_sbom por repo que recibió un commituna 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.

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=34

Una 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.

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:

  • actions cuesta 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.
  • artifacts recorre 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.
  • activity solo se cobra en un repositorio cuyo log se movió: la página de uno que no se movió es un 304 gratis.
  • commits, issueevents y la pasada incremental de issues solo 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 de issues se hace en todos los repositorios, activos o no.
  • outbound cuesta 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.

Pon su intervalo a 0.

every:
families:
artifacts: 0
joblogs: 0

Una familia apagada no escribe nada y no cuesta nada. Sus paneles del dashboard se quedan vacíos, que es la lectura honesta. Ver cadencias.

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=actions

De vez en cuando está bien. En cada pasada significa que las cadencias son demasiado rápidas para el número de repositorios.