Um bot de vídeo feito com vibe coding não aguentou o segundo usuário: como acabou rodando em seis VPS
Um amigo usou IA para criar o UNIQ, um bot de Telegram que transforma um vídeo em várias cópias para Reels, Shorts e TikTok. O protótipo funcionava enquanto havia apenas um usuário. Com o segundo, apareceram bloqueios, disco cheio e tarefas que se perdiam quando um worker caía. Os desenvolvedores migraram para PostgreSQL, uma fila com concessões temporárias e S3. Agora o serviço roda em seis VPS.
Processado por IA de Habr AI; editado por Hamidun News
Vibe coding funciona muito bem enquanto o projeto tem um único usuário e esse usuário é você. Um desenvolvedor do UNIQ contou no Habr como um bot de Telegram criado por um amigo com ajuda de IA se transformou em um serviço que eles podiam vender com confiança. A principal lição: escrever código é rápido, mas definir o que conta como comportamento correto do sistema continua sendo responsabilidade sua.
O ponto de partida e onde tudo quebrou
O UNIQ recebe um vídeo e gera de uma a dez versões para republicação: o FFmpeg altera parâmetros de enquadramento, velocidade, cor e áudio. O protótipo usava Python e SQLite e rodava no Mac do autor. O primeiro problema foi o disco: cada pedido mantém ao mesmo tempo o original, arquivos temporários e cópias prontas. Por isso, acrescentaram um limite de upload de 150 MB, um orçamento de espaço em disco e rotinas de limpeza.
A verdadeira virada aconteceu quando um segundo usuário entrou no teste. Enquanto o FFmpeg processava o vídeo de outra pessoa, ele abria menus e enviava seu próprio vídeo, e tudo esbarrava em bloqueios globais e estado espalhado. A equipe decidiu não reescrever o sistema em Go: mudar de linguagem não elimina um bloqueio global nem acrescenta núcleos. Em vez disso, separou as esperas de rede, as consultas ao banco e a codificação.
Uma fila que sobrevive a falhas
Para distribuir tarefas entre vários servidores, escolheram PostgreSQL: banco compartilhado, transações e bloqueios de linhas com FOR UPDATE SKIP LOCKED. O worker recebe uma concessão temporária sobre a tarefa. Se ele travar, outro assume o pedido quando o prazo expira. Para impedir que o primeiro sobrescreva o resultado ao voltar a responder, cada atribuição gera um novo token de proprietário, verificado em toda gravação de estado.
O plano de efeitos é salvo antecipadamente, e as cópias prontas são registradas em um checkpoint, permitindo que o segundo worker continue do ponto da falha. Uma solicitação repetida com o mesmo identificador retorna o receipt salvo, em vez de executar a operação novamente. Os desenvolvedores também reconhecem uma limitação: se o arquivo chegar ao Telegram antes de o registro de envio ser salvo, a cópia poderá chegar duas vezes. A idempotência interna não dá semântica exactly-once a uma API externa.
As moedas foram um desafio à parte. Elas acabaram exigindo um pequeno sistema contábil: lotes com seus próprios prazos de validade, reservas e histórico de operações. Quando um pedido é cancelado, as moedas não utilizadas voltam aos lotes originais com a validade anterior; caso contrário, o cancelamento vira uma assinatura que nunca expira. O pedido fixa a tarifa no momento da confirmação, e um ID único da transação externa impede que uma notificação de pagamento repetida credite o saldo duas vezes.
O ganho perceptível para o usuário veio de uma reorganização do fluxo, mais do que de uma otimização: a codificação foi separada da entrega, e as cópias são enviadas uma por vez. Em uma execução no ambiente de testes local, elas chegaram após 40, 70, 105, 136 e 171 segundos. Assim, a primeira ficou disponível 131 segundos antes da conclusão do pedido.
Os números de carga e seus limites
Depois de mover os vídeos para o S3 e adicionar o PgBouncer, com até 2000 conexões de clientes compartilhando 10 conexões de servidor, a equipe começou a medir os gargalos. Uma rajada de 1000 confirmações de pedidos levava 5,9 segundos, enquanto a espera acumulada por um único bloqueio SQL chegava a cerca de quarenta segundos. O bloqueio exclusivo global foi substituído por bloqueios por usuário, reduzindo a rajada para 3,2 segundos.
Aumentar o pool da aplicação de 8 para 16 conexões, com o PgBouncer limitado a 10, não acelerou nada: a fila apenas mudou de lugar. A codificação de 20 vídeos curtos de 720×1280 em 5 CPUs atingiu um platô já com 4–5 workers: cerca de 29 tarefas por minuto. Doze processos consumiram 3133 MiB de memória e foram mais lentos que cinco.
O menu processou 10 000 solicitações iniciais sem erros, mas a latência p95 ficou em torno de 30 segundos. Como os desenvolvedores observam com razão, aceitar uma solicitação e responder rapidamente a uma pessoa são coisas diferentes.
Que lições levar para o seu projeto
Os números foram obtidos com vídeos curtos em um ambiente de testes específico; não podem ser extrapolados para vídeos longos em 1080p nem para uma quantidade de usuários. As perguntas, porém, são universais. O que bloqueia o quê? Onde fica o estado? O que acontece se um worker morrer no meio de um pedido? O que ocorre quando um evento de pagamento se repete? A IA escreve código rapidamente, mas você terá que formular as respostas e verificá-las com testes por conta própria, de preferência antes da chegada do segundo usuário.
- 8 de nov. de 2026Stanford ensina alunos a enviar patches aos mantenedores: por dentro do curso CS146S
- 8 de nov. de 2026Ações de IA despencam enquanto mercado russo de IA médica fatura apenas 1,5 bilhão de rublos
- 8 de nov. de 2026Claude Code mantém as chaves do Datadog fora do alcance do agente: um proxy adiciona o token
- 8 de nov. de 2026Meta abre o Astryx: um sistema de design em React 19 e StyleX para pessoas e agentes de IA
Perguntas frequentes sobre a notícia
O que se sabe sobre O ponto de partida e onde tudo quebrou?
O UNIQ recebe um vídeo e gera de uma a dez versões para republicação: o FFmpeg altera parâmetros de enquadramento, velocidade, cor e áudio. O protótipo usava Python e SQLite e rodava no Mac do autor. O primeiro problema foi o disco: cada pedido mantém ao mesmo tempo o original, arquivos temporários e cópias prontas. Por isso, acrescentaram um limite de upload de 150 MB, um orçamento de espaço em disco e rotinas de limpeza. A verdadeira virada aconteceu quando um segundo usuário entrou no teste.
O que se sabe sobre Uma fila que sobrevive a falhas?
Para distribuir tarefas entre vários servidores, escolheram PostgreSQL: banco compartilhado, transações e bloqueios de linhas com FOR UPDATE SKIP LOCKED. O worker recebe uma concessão temporária sobre a tarefa. Se ele travar, outro assume o pedido quando o prazo expira. Para impedir que o primeiro sobrescreva o resultado ao voltar a responder, cada atribuição gera um novo token de proprietário, verificado em toda gravação de estado.
O que se sabe sobre Os números de carga e seus limites?
Depois de mover os vídeos para o S3 e adicionar o PgBouncer, com até 2000 conexões de clientes compartilhando 10 conexões de servidor, a equipe começou a medir os gargalos. Uma rajada de 1000 confirmações de pedidos levava 5,9 segundos, enquanto a espera acumulada por um único bloqueio SQL chegava a cerca de quarenta segundos. O bloqueio exclusivo global foi substituído por bloqueios por usuário, reduzindo a rajada para 3,2 segundos.
Test Frontier LLMs & Autonomous Agents in One Workspace
Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.
O essencial da IA — uma vez por semana
Sete histórias que realmente importaram, escolhidas a dedo. Sem ruído nem releases.
Pronto! Verifique seu e-mail para a confirmação.