GitHub Runner Self-Hosted vs Hosted: Quando Vale a Pena Rodar o Seu Próprio
Uma comparação prática entre os runners hospedados do GitHub Actions e runners self-hosted: custo, manutenção, performance, segurança e controle. Quando cada um faz sentido.
O dilema de quem paga a conta do CI
Muito se fala em otimizar pipeline de CI, mas pouca gente para pra olhar de onde vem a conta. O GitHub Actions é generoso no plano gratuito, com seus 2.000 minutos por mês em repositórios privados, e por um bom tempo isso é mais do que suficiente. O problema começa quando o time cresce, a suíte de testes engorda, os builds passam a rodar em paralelo e, de repente, aquele número confortável vira uma fatura que ninguém previu no orçamento.
E não é só dinheiro. É também aquela sensação de estar esperando uma máquina fria ser provisionada do zero a cada push, baixando dependências que você já baixou dez mil vezes, só pra rodar o mesmo
npm cide sempre.
É nesse momento que a pergunta aparece, geralmente num canal de engenharia às onze da noite: será que não vale a pena rodar nosso próprio runner? Se você se encontra nesse cenário, então o que vou trazer aqui é pra você. A resposta, como quase tudo em infraestrutura, é um sólido depende. E o objetivo deste post é desenhar com clareza de que é que depende.
O que cada modelo realmente é
Antes de comparar, vale alinhar o vocabulário, porque os dois modelos resolvem o mesmo problema por caminhos bem diferentes.
Um runner hospedado é uma máquina virtual efêmera que o GitHub provisiona, executa o seu job e descarta. Cada execução começa do zero, num ambiente limpo, com um conjunto pré-instalado de ferramentas, e some assim que termina. Você não administra nada, não atualiza nada, não se preocupa com disco cheio nem com kernel desatualizado. Em troca, você paga por minuto e aceita as restrições de hardware que o GitHub oferece.
Um runner self-hosted é uma máquina sua, seja um servidor no datacenter, uma VM na cloud, um container ou até aquele mini-PC empoeirado embaixo da mesa, na qual você instala o agente do GitHub Actions. Essa máquina se registra no repositório ou na organização e fica de prontidão esperando jobs. Você controla o hardware, o sistema operacional, as ferramentas instaladas e, principalmente, o estado entre execuções. Em troca, a manutenção é toda sua.
A diferença filosófica é essa: o hosted é gado, o self-hosted é bicho de estimação. Um você troca sem dó, o outro você cuida.
Custo: a primeira coisa que todo mundo olha
O argumento financeiro é o que costuma puxar a conversa, então vamos encarar de frente. Os runners hospedados são cobrados por minuto, com multiplicadores que variam conforme o sistema operacional. Linux é a opção mais barata, Windows custa o dobro e macOS chega a custar dez vezes mais por minuto. Quando o seu pipeline depende de runners macOS pra buildar app iOS, a conta escala numa velocidade que assusta.
O runner self-hosted, por outro lado, tem um custo que muda de natureza. Em vez de pagar por minuto consumido, você paga pelo hardware ocioso. Um servidor que roda 24 horas por dia custa o mesmo independentemente de você disparar dez ou dez mil builds nele. Isso inverte completamente a lógica de otimização: no hosted, cada segundo economizado é dinheiro de volta no bolso, enquanto no self-hosted o que importa é manter a máquina suficientemente ocupada pra justificar o custo fixo.
Existe um ponto de cruzamento, e é ele que você precisa calcular antes de qualquer decisão. Some seus minutos mensais, multiplique pelo custo por minuto do sistema operacional que você usa, e compare com o custo de manter uma máquina equivalente ligada o mês inteiro. Para times pequenos com pouco volume de CI, o hosted quase sempre ganha, porque a máquina dedicada ficaria parada a maior parte do tempo. Para times que estouram dezenas de milhares de minutos por mês, especialmente em macOS ou em builds pesados, o self-hosted começa a fazer sentido financeiro rápido.
Um detalhe que muita gente esquece de colocar na planilha: o custo de manutenção também é dinheiro. Aquela hora de engenheiro debugando por que o disco do runner encheu vale tanto quanto os minutos de CI que você economizou.
Performance: onde o self-hosted brilha
Aqui o self-hosted tem uma vantagem que vai além do dinheiro, e que costuma ser o motivo real por trás da migração. Como a máquina persiste entre execuções, você consegue manter cache quente de verdade. As dependências do node_modules, as imagens Docker já baixadas, os artefatos de build intermediários, tudo isso continua ali entre um job e outro. Um pipeline que leva oito minutos num runner hospedado, baixando tudo do zero, pode cair pra dois ou três minutos numa máquina que já tem o ambiente aquecido.
Some a isso a liberdade de escolher o hardware. Você pode rodar seus builds numa máquina com muito mais núcleos e memória do que os runners padrão do GitHub oferecem, ou plugar um cache de dependências local com latência irrisória, ou usar disco NVMe rápido onde o hosted te daria armazenamento genérico. Para builds de compilação pesada, suítes de teste massivas ou pipelines de machine learning que precisam de GPU, essa diferença não é marginal, é a diferença entre um CI que atrapalha e um CI que ajuda.
Os runners hospedados, é justo dizer, evoluíram bastante. Hoje existem opções de runners maiores, com mais núcleos, e o cache de Actions funciona razoavelmente bem para os casos comuns. Mas você sempre vai estar limitado ao catálogo de hardware que o GitHub decidiu oferecer, e o cache deles, por mais que ajude, ainda passa pela rede a cada execução.
Manutenção: o custo que não aparece na fatura
Agora a parte que ninguém gosta de falar. O runner hospedado tem custo de manutenção próximo de zero, e isso é o seu maior trunfo. O GitHub atualiza o sistema operacional, mantém as ferramentas em dia, garante o isolamento entre execuções e lida com toda a infraestrutura subjacente. Você escreve o workflow e esquece que existe uma máquina por baixo.
O self-hosted te devolve esse trabalho inteiro, e ele é mais do que parece à primeira vista. Você precisa atualizar o agente do runner quando o GitHub lança novas versões, manter o sistema operacional com patches de segurança, monitorar disco e memória, limpar o lixo que se acumula entre builds e garantir que uma execução não contamine a próxima. Aquele cache quente que te deu performance é a mesma coisa que pode te dar dor de cabeça quando um artefato corrompido de um build anterior faz o próximo falhar de um jeito impossível de reproduzir localmente.
A estratégia que resolve boa parte disso é usar runners efêmeros, geralmente em containers ou VMs descartáveis que são criados pra um único job e destruídos em seguida. Ferramentas como o actions-runner-controller no Kubernetes ou setups baseados em VMs com Terraform e Ansible automatizam exatamente isso. Você recupera o isolamento dos runners hospedados sem abrir mão do controle, mas paga o preço de manter essa orquestração funcionando. Não existe almoço grátis, apenas escolha de qual conta pagar.
Segurança: o ponto onde o self-hosted exige respeito
Existe uma recomendação que vale repetir até cansar: nunca use runners self-hosted em repositórios públicos sem isolamento rigoroso. A razão é simples e séria. Quando alguém abre um pull request de um fork num repositório público, o workflow daquele PR pode acabar executando na sua máquina. Num runner hospedado isso é inofensivo, porque o ambiente é destruído depois. Num runner self-hosted persistente, isso significa que código arbitrário de um desconhecido rodou na sua infraestrutura, com acesso potencial à rede interna, a segredos em cache e ao próprio host.
Esse é o tipo de detalhe que transforma uma economia de CI numa porta de entrada pra um incidente de segurança. Se você vai rodar self-hosted, faça em repositórios privados ou com runners efêmeros completamente isolados, em rede segmentada, sem acesso a nada que você não esteja disposto a expor. O modelo hosted, nesse quesito, te entrega isolamento de fábrica, e isso tem um valor real que raramente entra na conta de custo.
Um quadro pra fechar o ticket
Resumindo a comparação nos eixos que importam:
| Critério | Hospedado | Self-hosted |
|---|---|---|
| Custo inicial | Zero | Hardware ou VM |
| Custo por volume | Por minuto, escala com uso | Fixo, independente do uso |
| Performance | Limitada ao catálogo | Hardware e cache à sua escolha |
| Manutenção | Zero | Sua, integralmente |
| Isolamento | De fábrica | Você precisa construir |
| Segurança em repos públicos | Segura por padrão | Requer cuidado rigoroso |
| Tempo até o primeiro build | Imediato | Setup inicial necessário |
Considerações finais
A escolha entre runner hospedado e self-hosted não é uma questão de qual é melhor no absoluto, e desconfie de quem te vende uma resposta única. É uma questão de onde está o seu gargalo. Se a sua dor é custo de minutos estourando todo mês, especialmente em macOS ou em builds pesados, e você tem hardware ocioso ou conhecimento de infra no time, o self-hosted paga o investimento. Se a sua dor é não querer administrar mais uma coisa, e o seu volume de CI cabe confortavelmente no que você paga hoje, o hosted continua sendo a escolha mais sensata, e provavelmente a mais barata quando você soma o custo invisível da manutenção.
A abordagem mais madura que vejo na prática não é escolher um lado e cravar bandeira. É usar os dois. Runners hospedados para a maioria dos jobs, onde a conveniência ganha, e self-hosted para os casos específicos onde o hardware ou o custo justificam, como builds de GPU, suítes gigantes ou pipelines que rodam o dia inteiro. A pergunta certa nunca foi hosted ou self-hosted, e sim qual job pertence a qual runner.
Love to you all.