Banco de dados sem cerimônia

Esqueça migrations, Docker e AWS. Salve dados em 3 linhas.

A coleção nasce no primeiro insert. Sem schema, sem migration, sem container. Você manda um JSON, a tabela se cria sozinha com os tipos certos — inclusive o campo de embedding, que já vira busca vetorial. E o que fica no disco é um arquivo SQLite que abre no seu computador.

A partir de R$ 29,99/mês. O que muda entre os planos é o número de instâncias — o resto está em todos.

O problema

O buraco não é o banco. É o que vem antes dele.

Schema antes de saber o formato dos dados. Migration antes de ter dado. Container antes de ter usuário. Você queria salvar um registro e acabou decidindo versionamento de schema, política de IAM e estratégia de conexão — tudo antes da primeira linha entrar no banco.

O que isso custa hoje

  • Schema, migration e container três decisões de infraestrutura tomadas antes de existir um único registro — e antes de você saber o formato dele.
  • Se você precisou ler muito antes de rodar algo, a culpa é nossa abra uma issue e a gente conserta a documentação, não o seu entendimento.

O caminho inteiro

Instala, salva, lê — e busca por significado.

Delegue ao agente — ou faça à mão em cinco blocos.

Atalho · Delegar

Ou não escreva nada disso

Um arquivo de 5.156 bytes com a integração inteira — collections, busca vetorial, blobs e SQL. Cole a URL no Claude Code, no Cursor ou no Copilot e peça a integração: ele escreve os cinco blocos abaixo por você. O arquivo também lista o que não existe, para o agente não inventar API.

llms.txt
$ curl https://myinfrastructure.click/products/storage/llms.txt

# Infrastructure Storage — Master
# Implementation Guide (LLM-Ready)
> Collections, vetores, blobs
> e SQL: a integração inteira. ▊

1 · Instalar

Um pacote, zero dependências

O SDK são 4.371 bytes de ESM sem nenhuma dependência de runtime. Não há build step: o package.json aponta para o fonte.

bash
$ bun add @ciromaciel/storage-sdk

installed
  @ciromaciel/storage-sdk@1.2.1
2 packages [1362.00ms]

2 · Salvar

A coleção nasce aqui

A coleção "produtos" não existe antes desta chamada. A tabela se cria com os tipos inferidos deste objeto: número vira REAL, array de números vira F32_BLOB, o resto vira TEXT.

index.js
import Storage from
  '@ciromaciel/storage-sdk'

const storage = new Storage(
  BASE_URL,
  process.env.STORAGE_KEY,
)

await storage
  .collection('produtos')
  .insert({
    nome: 'Teclado Mecânico',
    preco: 350.5,
    tags: ['perifericos'],
  })

3 · Ler

Filtro, sem SQL

Operadores: $eq, $neq, $gt, $gte, $lt, $lte e $like. Repare que $like envolve o valor em % automaticamente — não dá para ancorar prefixo. E não existe OR: condições são sempre combinadas com AND.

index.js
const { data } = await storage
  .collection('produtos')
  .select({
    where: {
      nome: { $like: 'Teclado' },
    },
    limit: 10,
  })

4 · Buscar por significado

O mesmo insert já indexou o vetor

Array de números vira F32_BLOB e ganha um índice vetorial na hora — você não cria índice, não sobe Pinecone, não paga um segundo banco. A consulta é kNN pelo vector_top_k do libSQL, no mesmo select() do filtro comum, e topK vai até 100. Guarde o embedding ao lado do texto que ele representa: é a mesma linha, no mesmo arquivo.

index.js
// o embedding entra como campo comum
await storage.collection('memorias')
  .insert({
    texto: 'prefere modo escuro',
    embedding: [0.1, 0.2, 0.3],
  })

// e volta por similaridade
const { data } = await storage
  .collection('memorias')
  .select({
    vectorIndex: 'embedding',
    vector: await embed('tema do app'),
    vectorTopK: 3,
  })

5 · Conferir

A saída, colada do terminal

Não é exemplo plausível — é o que apareceu aqui, colado do terminal. O tags voltou como array, o preco como número, e o id e o created_at você não escreveu.

bash
$ curl .../produtos -H "x-api-key: sk_..."

{
  "data": [
    {
      "id": "0293cef6-1831...",
      "created_at": "2026-08-18 15:12:23",
      "nome": "Teclado Mecânico",
      "preco": 350.5,
      "tags": ["perifericos"]
    }
  ],
  "meta": {
    "total": 1,
    "page": 1,
    "last_page": 1,
    "limit": 50
  }
}

[200 em 0.256434s]

Model Context Protocol

Seu agente fala com o storage. Sem código no meio.

O Storage já era memória de agente antes de existir MCP: schema-less, busca vetorial nativa, um arquivo por instância. Faltava o agente usar isso sem alguém escrever a integração. São 13 ferramentas — 7 leem, 6 escrevem — na revisão 2026-07-28, a stateless.

O que o servidor NÃO oferece

  • Apagar a instância, apagar coleção, rotacionar a chave não existem como ferramenta. Um agente que leia "apague tudo" num documento não encontra o gatilho para obedecer.
  • Continuam no painel e na API REST onde há uma pessoa confirmando. Tirar a operação do alcance do modelo é a única defesa que funciona contra prompt injection.

Autentica das duas formas com a sua sk_ ou com OAuth 2.1 pelo Infrastructure Auth. As duas chegam na mesma instância.

Como o agente entra

Nenhuma chave no arquivo.

O token nasce no navegador e vale só na instância que você aprovou.

OAuth 2.1

Você aprova no navegador, uma vez

Sem header nenhum no comando. Na primeira chamada o servidor responde 401 apontando para o metadata; o cliente descobre o authorization server sozinho, abre o navegador e você aprova. O token vale só naquela instância — o id no endereço vira a audiência dele — e o escopo decide se escreve ou só lê. Em CI, onde não há navegador, a sua sk_ conecta direto.

bash
$ claude mcp add --transport http \
    infrastructure-storage \
    https://storage.manager.myinfrastructure.click/mcp/<id-da-instância>

→ 401 WWW-Authenticate
→ descobre o auth server
→ abre o navegador
✓ token com aud= esta instância ▊

O que muda na prática

Ninguém escreveu esse filtro

O agente não adivinha nomes de coleção nem de campo: ele consulta o schema antes, porque o storage é schema-less e não há como chutar. As três chamadas abaixo saíram de uma frase.

conversa
Você: "quantos produtos acima de 300?"

→ list_collections
  { "produtos": 1, "docs": 1 }

→ describe_collection("produtos")
  colunas: nome, preco (REAL), tags

→ query_collection
  { where: { preco: { $gt: 300 } } }

  1 documento. Teclado Mecânico,
  R$ 350,50.

Portabilidade

O que fica no disco é um
SQLITE PADRÃO.

Cada tenant tem um arquivo próprio, não uma linha com tenant_id numa tabela compartilhada. E esse arquivo abre na ferramenta que já vem no seu sistema — sem conversor, sem dump proprietário, sem nós no meio.

  • Um arquivo .sqlite por tenant, isolado no disco
  • file diz: SQLite 3.x database, UTF-8
  • sqlite3 arquivo.sqlite abre e imprime a tabela

Sem prisão

Um comando. E o banco está na sua máquina.

Não é um argumento — é um arquivo. Rode o comando com a sua chave e o banco desce inteiro, no formato que qualquer ferramenta SQLite abre. Sem ticket, sem exportador proprietário, sem esperar aprovação.

O que acontece quando você roda

  • VACUUM INTO, não uma cópia do disco a resposta é uma cópia consistente mesmo com escrita acontecendo no meio, e já compactada — sem páginas livres.
  • Content-Type: application/vnd.sqlite3 o navegador e o curl tratam como download. O nome vem com a data: infrastructure-storage-2026-08-18.sqlite
  • Autenticado pela sua chave sem x-api-key responde 401, com chave inválida responde 403, e cada chave só alcança o próprio arquivo.
  • A cópia temporária é apagada no servidor mesmo se a resposta falhar no meio. Não fica rastro do seu banco no nosso disco.

A ressalva que continua valendo se você usa busca vetorial, o arquivo carrega um índice libsql_vector_idx, que é extensão do libSQL. Os dados continuam legíveis e o .dump recupera tudo, mas PRAGMA integrity_check falha no sqlite3 padrão e o índice precisa ser recriado do outro lado. Quem não usa vetores tem um arquivo 100% padrão.

Sendo justo

O Supabase é excelente
— para os problemas de lá.

Postgres / Supabase

Onde eles são a resposta certa

Dado relacional, JOIN e integridade referencial

Postgres

Escrita concorrente alta (MVCC)

Postgres

Realtime, Auth e Edge Functions integrados

Supabase

Ecossistema, extensões e gente que já sabe operar

30 anos

Backup com restauração testada

Eles têm

Use eles se

Seu dado é relacional

O Supabase é excelente — para os problemas de lá.

Infrastructure Storage

Sem cerimônia

Guardar dados sem tomar decisão de infraestrutura antes de saber o formato deles — e que o que fique no disco seja um arquivo aberto.

  • A coleção nasce no primeiro insert, sem schema nem migration
  • Busca vetorial (kNN) no mesmo banco — sem um segundo serviço de vetor
  • Um arquivo .sqlite por tenant, isolado no disco
  • Export em um comando: baixa o banco em SQLite padrão
  • Leitura por chave plana até 1 milhão de documentos
  • SDK de 4.371 bytes, zero dependências de runtime

A régua

Os cinco eixos que decidem a escolha

A mesma tabela em toda página de produto do Infrastructure. Cada linha traz o número que medimos, a data e o método — não uma promessa.

Sair e levar tudo

Um comando

Um curl devolve o banco inteiro. Sem ticket, sem espera, sem falar com vendedor — o mesmo caminho no primeiro e no último dia.

Formato do export

SQLite 3 padrão

Abre em sqlite3, DBeaver, Python — sem conversor. Ressalva: com busca vetorial vem um índice libsql_vector_idx não padrão; os dados seguem legíveis, o índice precisa ser recriado.

Tempo até o primeiro dado salvo

1,9 s

Do bun add até o dado voltar: 1,36 s no pacote, 0,248 s no insert, 0,256 s na leitura. O relógio começa depois do cadastro, que é onde você pega a API key.

Custo em R$

R$ 29,99 a R$ 99,99/mês

Starter, Pro e Scale — o que muda é o número de instâncias (3, 9 ou 99), e esse é o único limite verificado no servidor. Não há cota de tamanho, de coleções nem de documentos. Os valores desta linha vêm do mesmo catálogo que a seção de preço lê ao vivo.

Latência de leitura para usuário em São Paulo

0,15 ms no banco

A requisição completa de São Paulo leva 232 ms (mediana de 15 amostras, 18/08/2026, curl). Desses, 0,15 ms é o banco e o resto é a viagem até iad (EUA) — o número vem do próprio servidor, no campo meta.duration.

Se algum destes números não bater no seu caso, escreva. A gente mede de novo e corrige a linha.

Preço

3, 9 ou 99 instâncias

Pega uma chave e testa. Leva dois minutos.

Sem “fale com vendas”: você escolhe o plano na tela acima e começa. Se travar em algum passo, é bug de documentação e a gente conserta.

FAQ

As objeções, na ordem em que elas aparecem

Achou um limite que não está escrito aqui?

Fala direto com quem escreveu o código. Se você encontrou onde quebra, a gente quer publicar isso na página antes do próximo visitante descobrir sozinho.