Quanto custa guardar arquivos e imagens dos usuários

Guardar uploads custa a soma de três linhas: GB armazenados por mês, requisições de envio e leitura e a saída de dados quando alguém baixa. Em muitos provedores, a saída pesa mais que o armazenamento.

Atualizado em 7 min de leitura

Objetivos de aprendizado

Depois de ler este artigo, você vai conseguir:

  • Entender as linhas que compõem a conta de guardar arquivos de usuários
  • Estimar o custo de um ano de uploads com uma conta passo a passo
  • Reduzir o gasto com compressão, regras de ciclo de vida e cache
Nesta página

Foto de perfil, anexo de chat, comprovante em PDF, imagem de produto: quase todo app acaba guardando arquivos que os usuários enviam. No começo o volume é pequeno e a conta nem aparece. O problema é que uploads se acumulam. Ao contrário do tráfego, que sobe e desce, o que foi guardado continua lá no mês seguinte, e no outro. Por isso vale estimar um ano de uploads antes de escolher onde guardar.

Os números deste artigo são hipotéticos, escolhidos para facilitar a conta, e estão em dólar americano. Não são preços de nenhum provedor; os valores reais mudam, variam por região e ficam nas páginas oficiais, então confira as páginas oficiais da AWS e da Backblaze antes de decidir.

custo por mêsmês 1mês 6mês 12Saídasegue as exibiçõesRequisiçõesestáveisArmazenamentocresce todo mês
Cada mês soma arquivos novos aos antigos, então o armazenamento só cresce; a saída segue as exibições.

Do que é feita a conta de guardar uploads?#

Num object storage, que é onde uploads costumam morar (veja o que é object storage), a fatura tem até três linhas:

  • Armazenamento: preço por GB guardado por mês. É a linha que cresce sozinha, porque cada mês soma os arquivos novos aos antigos.
  • Requisições: cada envio (PUT) e cada leitura (GET) pode ser cobrado, em geral por milhar. Pesa em apps com muitos arquivos pequenos, como miniaturas.
  • Saída de dados (egress): preço por GB que sai do storage para a internet quando alguém abre o arquivo. Em vários provedores, é a linha mais cara. O artigo sobre taxas de saída explica a mecânica.

Fora do storage, entram o processamento (gerar miniaturas consome CPU do seu servidor) e, se houver, a CDN na frente dos arquivos públicos.

Como os provedores cobram cada linha?#

Dois modelos de cobrança, com os valores hipotéticos usados na conta mais adiante:

Item (valor hipotético) Provedor A: cobra cada linha Provedor B: franquia de saída
Armazenamento US$ 0,02 por GB/mês US$ 5 por TB/mês
Envio (PUT, COPY, POST, LIST) US$ 0,01 por 1.000 Sem cobrança
Leitura (GET) US$ 0,001 por 1.000 Sem cobrança
Saída para a internet Primeiros 100 GB/mês sem cobrança, depois US$ 0,10 por GB Sem cobrança até 2 vezes o volume armazenado, depois US$ 0,02 por GB

Os dois desenhos existem no mercado. O S3 cobra cada linha separada e tem classes mais baratas para arquivos pouco acessados, como o provedor A. O B2 tem armazenamento mais barato por GB e embute requisições e parte da saída, como o provedor B. Nenhum é mais barato em todos os casos: a resposta depende de quanto você guarda e de quanto é baixado.

Como estimar o volume de uploads?#

Faça a conta com quatro números:

GB por mês = uploads por mês × tamanho médio × número de versões guardadas
GB guardados no mês N = GB por mês × N

O que mais mexe na conta é o número de versões. Muitos apps guardam o original enviado, uma versão de exibição e uma miniatura. Uma foto de celular tem alguns MB; a mesma imagem redimensionada em WebP para exibição fica em algumas centenas de KB, e a miniatura em dezenas.

Exemplo hipotético: um app com 5.000 usuários ativos, cada um enviando 10 fotos por mês. Cada upload gera um original de 3 MB, uma versão de exibição de 300 KB e uma miniatura de 40 KB. Por mês, o app recebe 1 milhão de exibições da versão grande e 3 milhões de miniaturas.

O script abaixo calcula a conta do 12º mês e roda em qualquer versão recente do Node.js:

js
// custo-uploads.mjs: node custo-uploads.mjs
// Exemplo hipotético em US$: o provedor A cobra cada linha; o B tem franquia de saída.
// Não são preços de nenhum provedor; troque pelos das páginas oficiais antes de usar o resultado.
const uploadsPorMes = 50_000; // 5.000 usuários x 10 fotos
const meses = 12;
const mbPorUpload = 3 + 0.3 + 0.04; // original + versão de exibição + miniatura
const putsPorUpload = 3;
const getsPorMes = 4_000_000; // 1 milhão de exibições + 3 milhões de miniaturas
const gbBaixadosPorMes = 1_000_000 * 0.0003 + 3_000_000 * 0.00004; // 420 GB

const gbGuardados = (uploadsPorMes * mbPorUpload * meses) / 1000;

const provedorA = {
  armazenamento: gbGuardados * 0.02,
  requisicoes:
    ((uploadsPorMes * putsPorUpload) / 1000) * 0.01 +
    (getsPorMes / 1000) * 0.001,
  saida: Math.max(0, gbBaixadosPorMes - 100) * 0.1,
};
const provedorB = {
  armazenamento: (gbGuardados / 1000) * 5, // US$ 5 por TB-mês
  requisicoes: 0, // sem cobrança por requisição
  saida: Math.max(0, gbBaixadosPorMes - 2 * gbGuardados) * 0.02, // franquia de 2x o armazenado
};

console.log(`Guardado no mês ${meses}: ${gbGuardados.toFixed(0)} GB`);
for (const [nome, c] of Object.entries({ "Provedor A": provedorA, "Provedor B": provedorB })) {
  const total = c.armazenamento + c.requisicoes + c.saida;
  console.log(
    `${nome}: armazenamento US$ ${c.armazenamento.toFixed(2)}, ` +
      `requisições US$ ${c.requisicoes.toFixed(2)}, ` +
      `saída US$ ${c.saida.toFixed(2)}, total US$ ${total.toFixed(2)}`,
  );
}

Resultado, com cerca de 2 TB guardados no 12º mês:

Provedor Armazenamento Requisições Saída Total do mês 12
Provedor A US$ 40,08 US$ 5,50 US$ 32,00 US$ 77,58
Provedor B US$ 10,02 US$ 0,00 US$ 0,00 US$ 10,02

Os números saem dos valores hipotéticos, sem impostos nem câmbio. No provedor B, a saída só fica sem cobrança porque o volume baixado (420 GB) é menor que 2 vezes o armazenado; no primeiro mês, com só 167 GB guardados, a franquia seria de 334 GB e os 86 GB restantes seriam cobrados.

O que mais pesa: armazenamento, requisições ou saída?#

Rode o mesmo script sem guardar o original (troque mbPorUpload para 0.3 + 0.04). O armazenamento do 12º mês cai de 2.004 GB para 204 GB, e o total no provedor A cai de US$ 77,58 para US$ 41,58. A saída continua igual, em US$ 32,00, porque os visitantes nunca baixavam o original.

O exemplo deixa três conclusões:

  1. O original é o maior custo de armazenamento. Ele ocupa quase 90% do espaço no exemplo e não é exibido a ninguém.
  2. A saída acompanha as exibições, não o volume guardado. Num app popular ela passa o armazenamento com facilidade, em provedores que cobram egress.
  3. Requisições raramente dominam, a não ser com milhões de arquivos minúsculos ou leituras repetidas sem cache.

Quais custos escondidos aparecem?#

  • Arquivos órfãos. O usuário apaga a conta ou troca a foto, e o arquivo antigo fica no bucket para sempre. Apague o objeto junto com o registro no banco.
  • Uploads multipart incompletos. Em envios grandes divididos em partes, as partes de um upload abandonado continuam ocupando espaço. A AWS recomenda uma regra de ciclo de vida com AbortIncompleteMultipartUpload para apagá-las após alguns dias. Veja como enviar arquivos grandes.
  • Versionamento ligado. Com versionamento, sobrescrever um arquivo não apaga a versão anterior, e cada versão é cobrada.
  • Duração mínima em classes frias. Classes de acesso infrequente cobram um tempo mínimo de armazenamento (30 dias no S3 Standard-IA, 90 a 180 dias nas classes Glacier). Mover para lá arquivos que serão apagados logo pode sair mais caro.
  • Imagens no banco ou no disco do servidor. Guardar bytes no banco de dados encarece o disco e os dumps; guardar no disco local da aplicação prende os arquivos a uma máquina. Compare em imagens no banco vs object storage e object storage vs disco local.
  • Hotlinking. Outro site que usa o link direto das suas imagens gera saída na sua conta.

Como reduzir o custo de guardar uploads?#

Em ordem de retorno:

  1. Redimensione e comprima no upload. Gere a versão de exibição em WebP ou AVIF com largura máxima definida e decida se o original precisa mesmo ficar.
  2. Limite tamanho e tipo de arquivo antes de aceitar o envio. Um limite de 10 MB e uma lista de extensões permitidas evitam vídeos de 2 GB num campo de foto de perfil.
  3. Use regras de ciclo de vida para apagar temporários, mover originais para uma classe mais barata e limpar uploads incompletos. Veja regras de ciclo de vida.
  4. Ponha cache na frente dos arquivos públicos, com Cache-Control longo em arquivos que não mudam, para que a saída do storage aconteça uma vez por arquivo e não por visita.
  5. Envie direto do navegador para o storage com uma URL assinada, para o arquivo não passar pelo seu servidor e não consumir a banda dele.
  6. Escolha o provedor pela linha que mais pesa no seu caso. Muita exibição pede saída barata; muito volume guardado pede armazenamento barato. O artigo sobre custo de object storage compara modelos de preço.

Como fazer isso na Square Cloud#

Na Square Cloud, os uploads podem ir para o Blob Storage, um object storage com API compatível com S3 (aws-cli, rclone, boto3 e SDKs da AWS), API REST e painel. Ele não cobra taxa de saída nem de entrada, então a linha de saída do exemplo não existe aqui: o download não tem cobrança de banda. O limite que existe é um rate limit de requisições S3 por plano.

Todo plano inclui uma cota de Blob, de 5 GB a 250 GB. O Hobby, a partir de R$ 12,49 por mês, inclui de 5 a 15 GB. Arquivos públicos são servidos por uma CDN global na edge; arquivos privados abrem por link temporário de até 24 horas ou por link de compartilhamento revogável de até 30 dias.

As regras por pasta cobrem boa parte dos cuidados deste artigo: tamanho máximo, extensões permitidas, expiração, cache e limpeza automática. Arquivos podem ter até 10 GB, e o multipart só é obrigatório acima de 100 MB. Veja os detalhes na página do Blob Storage.

Blob Storage

Object storage compatível com S3, sem taxa de saída

Saiba mais

Perguntas frequentes

Quanto custa guardar 1 TB de imagens por mês?

Só o armazenamento é o volume em GB vezes o preço por GB-mês do provedor. Supondo US$ 0,02 por GB-mês (valor hipotético), 1 TB (1.000 GB) sai por US$ 20 por mês; num provedor que cobrasse US$ 5 por TB-mês, também hipotético, sairia por US$ 5. Requisições e saída de dados entram à parte.

É mais barato guardar imagens no banco de dados?

Quase nunca. O disco de um banco costuma custar mais por GB que um object storage, as imagens incham os dumps e cada leitura passa pelo banco. O padrão é guardar o arquivo no object storage e só a chave no banco.

O que mais pesa na conta de uploads?

Depende do uso. Num app com muitas exibições, a saída de dados costuma ser a maior linha em provedores que cobram egress. Num app que guarda originais grandes e quase não exibe, o armazenamento acumulado domina.

Devo guardar a foto original que o usuário enviou?

Só se você precisar dela, por exemplo para reprocessar depois. Uma foto de celular tem alguns MB, e a versão de exibição em WebP pode ter algumas centenas de KB. Descartar o original ou movê-lo para uma classe mais barata corta a maior parte do armazenamento.

Próximo artigoObject storage ou disco da aplicação: onde salvar arquivosDisco da aplicação é rápido, mas fica preso a uma máquina; object storage é acessível de qualquer lugar. Compare os dois e veja quando usar cada um.