[{"data":1,"prerenderedAt":272},["ShallowReactive",2],{"blog-alternates-\u002Fplataforma-dooh-cloudflare-native":3,"blog-nav-facets-pt":6,"blog-post-pt-plataforma-dooh-cloudflare-native":13},{"pt":4,"en":5},"\u002Fplataforma-dooh-cloudflare-native","\u002Fen\u002Fdooh-platform-on-cloudflare",{"populatedCategories":7,"authorCount":12},[8,9,10,11],"operacao","produto","dooh","engenharia",1,{"post":14,"authorIndex":216,"counterpartSlug":222,"related":223},{"id":15,"title":16,"authors":17,"body":19,"category":11,"cover":197,"description":200,"discussionUrl":201,"draft":202,"extension":203,"featured":202,"highlights":201,"meta":204,"navigation":205,"ogImage":198,"path":206,"publishedAt":207,"seo":208,"slug":209,"sourceHash":201,"stem":210,"tags":211,"translate":205,"translatedFrom":201,"translationKey":209,"translationStatus":201,"updatedAt":201,"__hash__":215},"posts_pt\u002Fpt\u002Fposts\u002Fplataforma-dooh-cloudflare-native.md","Por que a Lucimark roda inteira na Cloudflare",[18],"paulo-ramires",{"type":20,"value":21,"toc":189},"minimark",[22,26,29,34,37,71,74,78,93,96,99,129,136,139,143,156,162,168,172,175,186],[23,24,25],"p",{},"Toda plataforma de DOOH resolve o mesmo problema básico: uma tela em algum lugar precisa saber o que tocar, agora, mesmo que a internet daquele ponto caia três vezes por dia. A partir daí as decisões divergem bastante.",[23,27,28],{},"A nossa foi rodar tudo na borda da Cloudflare. Sem servidor de aplicação, sem fila gerenciada de terceiros, sem Docker em lugar nenhum — nem em desenvolvimento.",[30,31,33],"h2",{"id":32},"o-desenho","O desenho",[23,35,36],{},"Quatro peças fazem o trabalho pesado:",[38,39,40,48,54,60],"ul",{},[41,42,43,47],"li",{},[44,45,46],"strong",{},"Workers"," servem a API inteira (Hono). Nenhuma requisição de player passa por um datacenter fixo: ela é atendida no ponto de presença mais perto da tela.",[41,49,50,53],{},[44,51,52],{},"D1"," guarda o catálogo global — tenants, usuários, diretório de players.",[41,55,56,59],{},[44,57,58],{},"R2"," guarda a mídia. Sem custo de egresso, o que importa quando cada tela baixa os mesmos arquivos de vídeo.",[41,61,62,65,66,70],{},[44,63,64],{},"Durable Objects"," guardam o estado de cada cliente. Um ",[67,68,69],"code",{},"TenantDO"," por organização, com SQLite embutido.",[23,72,73],{},"A quarta é a que mais define o resto.",[30,75,77],{"id":76},"um-durable-object-por-cliente","Um Durable Object por cliente",[23,79,80,81,84,85,88,89,92],{},"O instinto normal seria uma tabela ",[67,82,83],{},"playlists"," com uma coluna ",[67,86,87],{},"tenant_id",", e um ",[67,90,91],{},"WHERE"," em toda query. Funciona, e é onde quase todo SaaS começa.",[23,94,95],{},"Nós fomos por outro caminho: cada organização tem o seu próprio Durable Object, com o seu próprio banco. Playlists, agendamentos, provas de veiculação e assets daquele cliente vivem lá dentro, e em lugar nenhum além disso.",[23,97,98],{},"Isso compra três coisas de uma vez:",[100,101,102,112,123],"ol",{},[41,103,104,107,108,111],{},[44,105,106],{},"Isolamento por construção."," Não existe query que possa vazar dados entre clientes, porque não existe uma tabela compartilhada para vazar. O erro clássico de esquecer o ",[67,109,110],{},"WHERE tenant_id"," deixa de ser possível.",[41,113,114,117,118,122],{},[44,115,116],{},"Coordenação sem fila."," Um DO é ",[119,120,121],"em",{},"single-threaded"," por definição. Quando dez telas do mesmo cliente reconectam ao mesmo tempo depois de uma queda de energia, elas conversam com o mesmo objeto, em ordem. Não precisamos de lock distribuído para nada disso.",[41,124,125,128],{},[44,126,127],{},"Localidade."," O objeto migra para perto de quem mais o usa.",[23,130,131,132,135],{},"O preço é real e vale dizer: você perde a query global. \"Quantas telas estão ativas na plataforma inteira?\" deixa de ser um ",[67,133,134],{},"SELECT COUNT(*)"," e vira um fan-out ou uma projeção que você mantém de propósito. Toda pergunta que atravessa clientes passa a exigir trabalho explícito.",[23,137,138],{},"Para o nosso caso, valeu. As perguntas que importam no dia a dia — \"essa playlist mudou?\", \"essa tela está viva?\", \"o que tocou ontem nessa tela?\" — são todas dentro de um cliente só.",[30,140,142],{"id":141},"o-que-doeu","O que doeu",[23,144,145,148,149,151,152,155],{},[44,146,147],{},"Migrações dentro do DO."," Migrar um banco central é uma operação; migrar N bancos, cada um acordando quando o cliente aparece, é outra. Nossa regra hoje é dura: o SQL que roda no boot do ",[67,150,69],{}," é só DDL e tem que ser barato. Qualquer backfill pesado vai para um alarm ou ",[67,153,154],{},"waitUntil",", fora do caminho crítico. Aprendemos isso da forma normal — um boot que ficou lento demais.",[23,157,158,161],{},[44,159,160],{},"Limites de CPU por requisição."," Workers não são o lugar para transcodificar vídeo. Nada que seja pesado de CPU roda em linha; ou vai para um serviço próprio, ou vira Workflow.",[23,163,164,167],{},[44,165,166],{},"Observabilidade."," Estado espalhado por milhares de objetos não aparece num dashboard sozinho. Custa esforço deliberado projetar o que importa para fora.",[30,169,171],{"id":170},"o-que-não-precisamos-construir","O que não precisamos construir",[23,173,174],{},"A parte mais fácil de subestimar é o que some do backlog.",[23,176,177,178,181,182,185],{},"Não temos servidor para escalar, nem cluster para atualizar, nem certificado TLS para renovar, nem CDN para configurar na frente da mídia. ",[67,179,180],{},"wrangler dev"," sobe o stack inteiro na máquina do dev — sem ",[67,183,184],{},"docker compose",", sem Postgres local, sem seis containers para lembrar de derrubar.",[23,187,188],{},"Para um time pequeno operando uma rede de telas que precisa ficar de pé, essa é a decisão que mais rende.",{"title":190,"searchDepth":191,"depth":191,"links":192},"",2,[193,194,195,196],{"id":32,"depth":191,"text":33},{"id":76,"depth":191,"text":77},{"id":141,"depth":191,"text":142},{"id":170,"depth":191,"text":171},{"src":198,"alt":199},"\u002Fimg\u002Fposts\u002Fplataforma-dooh-cloudflare-native\u002Fplataforma-dooh-cloudflare-native-cover.png","Ilustração de uma rede de telas distribuída ao redor de camadas abstratas de compute, banco, mídia e estado.","Workers, D1, R2 e um Durable Object por cliente. O que ganhamos, o que doeu e por que não existe um Docker no nosso stack.",null,false,"md",{},true,"\u002Fpt\u002Fposts\u002Fplataforma-dooh-cloudflare-native","2026-08-12",{"title":16,"description":200},"plataforma-dooh-cloudflare-native","pt\u002Fposts\u002Fplataforma-dooh-cloudflare-native",[212,213,214],"cloudflare","arquitetura","durable-objects","aiADBGMPhoQl-lLsv8OuuFjG45VQKOUxEI2J6sSbnck",{"paulo-ramires":217},{"handle":18,"name":218,"role":219,"avatar":220,"description":221},"Paulo R.","Fundador e CTO","\u002Fimg\u002Fauthors\u002Fpaulo-ramires.jpg","Fundador da Lucimark. Constrói a plataforma de ponta a ponta — do player Android na tela até os Workers que servem a API.","dooh-platform-on-cloudflare",[224,239,255],{"path":225,"title":226,"description":227,"slug":228,"translationKey":229,"category":11,"tags":230,"authors":233,"publishedAt":234,"updatedAt":201,"draft":202,"featured":202,"cover":235,"ogImage":236,"discussionUrl":201,"translationStatus":201,"readingMinutes":238},"\u002Fpt\u002Fposts\u002Fmudanca-schema-alarm-30s-noite-bilhao-linhas","Uma mudança de schema, um alarm de 30 segundos e uma noite de um bilhão de linhas","Como uma migração de Proof of Play em Cloudflare Durable Objects virou um loop de armazenamento sem limite — e o radar que construímos para que o próximo não se esconda.","mudanca-schema-alarm-30s-noite-bilhao-linhas","schema-change-do-storage-storm",[212,214,231,232],"proof-of-play","cost-observability",[18],"2026-09-04",{"src":236,"alt":237},"\u002Fimg\u002Fposts\u002Fmudanca-schema-alarm-30s-noite-bilhao-linhas\u002Fmudanca-schema-alarm-30s-noite-bilhao-linhas-cover.png","Ilustração de um nó de schema, pulsos de alarm e uma tempestade de dados em âmbar sobre fundo escuro.",16,{"path":240,"title":241,"description":242,"slug":243,"translationKey":243,"category":9,"tags":244,"authors":248,"publishedAt":249,"updatedAt":201,"draft":202,"featured":202,"cover":250,"ogImage":251,"discussionUrl":201,"translationStatus":201,"readingMinutes":254},"\u002Fpt\u002Fposts\u002Fcomo-colocar-primeira-tela-lucimark","Como colocar sua primeira tela no ar com a Lucimark","Um guia direto para transformar uma TV em tela digital, publicar a primeira imagem e testar a instalação.","como-colocar-primeira-tela-lucimark",[245,246,247],"primeira-tela","instalacao","digital-signage",[18],"2026-09-05",{"src":251,"alt":252,"credit":253},"\u002Fimg\u002Fposts\u002Fcomo-colocar-primeira-tela-lucimark\u002Fhero.jpg","Ilustração de uma tela vertical em uma confeitaria, instalada em uma moldura de ACM adesivada.","Ilustração inspirada em foto fornecida pela Nena Bolos.",7,{"path":256,"title":257,"description":258,"slug":259,"translationKey":259,"category":10,"tags":260,"authors":265,"publishedAt":249,"updatedAt":201,"draft":202,"featured":202,"cover":266,"ogImage":270,"discussionUrl":201,"translationStatus":201,"readingMinutes":271},"\u002Fpt\u002Fposts\u002Fcomo-vender-anuncios-em-telas-dooh","Como vender anúncios em telas: um plano para conquistar os primeiros 10 anunciantes","Aprenda a estruturar sua oferta de mídia DOOH, encontrar anunciantes locais, apresentar uma proposta e acompanhar campanhas para buscar renovações.","como-vender-anuncios-em-telas-dooh",[10,261,262,263,264],"rede-dooh","vendas","anunciantes","prospeccao",[18],{"src":267,"alt":268,"credit":269},"\u002Fimg\u002Fposts\u002Fcomo-vender-anuncios-em-telas-dooh\u002Fconversa-com-anunciante-local.webp","Duas pessoas conversam em uma loja de alimentação saudável enquanto observam imagens de telas em academias em um tablet.","Uma proposta começa pela conexão entre o negócio do anunciante e os pontos da rede. Cena ilustrativa gerada por IA.","\u002Fimg\u002Fposts\u002Fcomo-vender-anuncios-em-telas-dooh\u002Fconversa-com-anunciante-local-og.jpg",11,1788649408334]