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.
$ 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.
$ 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.
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.
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.
// 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.
$ 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.
$ 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.
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
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.