TL;DR: Construí um sistema completo de gestão financeira pessoal usando apenas Object Storage (S3). Sem PostgreSQL, sem MongoDB, sem Redis. Resultado: infraestrutura de ~R$1/mês com performance surpreendente.
A Provocação
Durante uma conversa com alguns amigos, surgiu a pergunta: "Você realmente precisa de um banco de dados para tudo?"
A resposta padrão seria: "Claro! Como você vai fazer queries? E as transações? E os índices?"
Mas e se... não precisássemos?
E se pudéssemos construir um sistema funcional de controle financeiro usando apenas Object Storage?
Spoiler: Funcionou. E funcionou bem.
O Problema Real
Como desenvolvedor, gerenciar finanças pessoais sempre foi caótico para mim:
- 📂 Faturas de cartão espalhadas no email
- 🧾 Comprovantes em pastas desorganizadas no Drive
- 💼 Recibos de investimentos perdidos
- 📊 Documentos do IR em diversos lugares
- 🔍 Impossível encontrar algo quando precisa
Pior: tentei usar apps prontos, mas todos tinham problemas:
- Apps mobile: Ótimos para registrar gastos, péssimos para documentos
- Google Drive: Falta estrutura e automação
- Planilhas: Funcionam até você ter 500 linhas
- Apps de terceiros: Lock-in + custos recorrentes altos
Eu queria algo simples, barato e que EU controlasse.
Deploy: 1 Minuto
Usei Docker Compose para tornar o deploy trivial:
version: '3.8'
services:
backend:
build: ./backend
ports:
- "8000:8000"
environment:
- BUCKET=${BUCKET}
- ACCESS_KEY=${ACCESS_KEY}
- SECRET_KEY=${SECRET_KEY}
frontend:
build: ./frontend
ports:
- "3000:80"
depends_on:
- backend
Deploy:
git clone https://github.com/mcruvinel/NimbusVault
cd NimbusVault
cp .env.example .env # Configure suas credenciais
docker compose up -d
Pronto. Sistema rodando.
A Ideia Maluca
"E se eu usar S3 como 'banco de dados'?"
Meu primeiro pensamento foi: "Isso é burrice, S3 não foi feito pra isso"
Mas então percebi algumas coisas:
-
S3 tem estrutura hierárquica (
categoria/arquivo.pdf) - list_objects_v2 é como um SELECT com filtros
- URLs pré-assinadas eliminam proxy de arquivos
- Durabilidade de 99.999999999% (melhor que meu PostgreSQL caseiro)
- Custo ridiculamente baixo para uso pessoal
Decidi testar. O pior que poderia acontecer era perder um fim de semana.
A Solução: NimbusVault
Construí o NimbusVault em um fim de semana. O conceito é simples:
Object Storage organizado = Banco de dados funcional
Arquitetura
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ React │─────▶│ FastAPI │─────▶│ MagaluCloud │
│ Frontend │ │ Backend │ │ Object Storage │
└─────────────┘ └──────────────┘ └─────────────────┘
Tailwind UI boto3 + S3 11 nines durability
Estrutura "Tabelas"
Em vez de tabelas SQL, uso prefixos como categorias:
finance-bucket/
├── despesas-mensais/
│ ├── fatura-cartao-out-2025.pdf
│ ├── recibo-aluguel-out.pdf
│ └── recibo-energia-outubro.pdf
├── receitas/
│ ├── holerite-outubro-2025.pdf
│ └── freelance-projeto-x.pdf
├── investimentos/
│ ├── tesouro-direto-setembro.pdf
│ └── extrato-corretora-out.pdf
└── impostos/
├── darf-irpf-2024.pdf
└── comprovante-iptu.pdf
Simples. Óbvio. Funcional.
Implementação
Backend Minimalista (FastAPI)
O backend tem menos de 200 linhas. Não é exagero.
from fastapi import FastAPI, UploadFile, Form, File
import boto3
app = FastAPI(title="NimbusVault")
s3 = boto3.client(
"s3",
endpoint_url=ENDPOINT_URL,
aws_access_key_id=ACCESS_KEY,
aws_secret_access_key=SECRET_KEY,
)
@app.post("/upload")
async def upload_file(category: str = Form(...), file: UploadFile = File(...)):
"""Upload de documento financeiro"""
key = f"{category}/{file.filename}"
content = await file.read()
s3.put_object(
Bucket=BUCKET,
Key=key,
Body=content,
ContentType=file.content_type,
)
return {"status": "ok", "key": key}
@app.get("/files")
def list_files(category: str = None):
"""Lista documentos (opcionalmente filtrados por categoria)"""
params = {"Bucket": BUCKET}
if category:
params["Prefix"] = f"{category}/"
response = s3.list_objects_v2(**params)
files = []
for obj in response.get('Contents', []):
# Gera URL pré-assinada (válida por 1 hora)
url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': BUCKET, 'Key': obj['Key']},
ExpiresIn=3600
)
files.append({
"key": obj["Key"],
"size": obj["Size"],
"modified": obj["LastModified"],
"url": url
})
return {"files": files}
Isso é tudo. Sério.
Frontend Responsivo (React + Tailwind)
Interface clean com drag-and-drop:
const NimbusVault = () => {
const [category, setCategory] = useState('despesas-mensais');
const [files, setFiles] = useState([]);
const handleUpload = async (e) => {
const formData = new FormData();
formData.append('category', category);
formData.append('file', e.target.files[0]);
await fetch('/api/upload', {
method: 'POST',
body: formData,
});
loadFiles();
};
return (
<div>
<CategorySelector value={category} onChange={setCategory} />
<UploadZone onUpload={handleUpload} />
<FileList files={files} />
</div>
);
};
Features Surpreendentes
1. URLs Pré-assinadas (Game Changer)
Em vez de fazer o backend servir arquivos (gastando banda e CPU), gero URLs temporárias que apontam direto pro S3:
presigned_url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': BUCKET, 'Key': 'receitas/holerite.pdf'},
ExpiresIn=3600 # 1 hora
)
Vantagens:
- ✅ Download direto do S3 (super rápido)
- ✅ Backend não processa tráfego
- ✅ Segurança: URLs expiram automaticamente
- ✅ Funciona com
<a download>nativamente
2. Busca "Good Enough"
Não tenho Elasticsearch, mas funciona:
# Backend lista TODOS os arquivos (rápido até ~10k objetos)
all_files = s3.list_objects_v2(Bucket=BUCKET)
# Frontend filtra com JavaScript
const filteredFiles = files.filter(f =>
f.key.toLowerCase().includes(searchQuery.toLowerCase())
);
Para 99% dos casos de uso pessoal (< 5000 documentos), isso é mais que suficiente.
3. "Particionamento" Natural
Usar prefixos como categorias é essencialmente particionamento:
# Lista APENAS despesas (rápido)
s3.list_objects_v2(Bucket=BUCKET, Prefix="despesas-mensais/")
# Lista APENAS investimentos (rápido)
s3.list_objects_v2(Bucket=BUCKET, Prefix="investimentos/")
Mesmo com 10.000 arquivos, listar uma categoria específica é instantâneo.
4. Versionamento Grátis
S3 tem versionamento nativo. Ativei e agora tenho audit trail de graça:
aws s3api list-object-versions \
--bucket finance-bucket \
--prefix despesas-mensais/fatura.pdf
Alguém deletou um documento importante? s3.get_object(VersionId=...) e recuperei.
Por que MagaluCloud?
Testei AWS S3, mas os custos no Brasil são altos (transferência de dados internacional).
MagaluCloud foi uma revelação:
Vantagens
- Datacenters no Brasil → latência <50ms (vs 150ms+ AWS EUA)
- Preços acessíveis → R$0,06/GiB/mês de storage (Cold Instant)
- API S3-compatível → boto3 funciona sem alteração
- Transferência barata → R$0,20/GiB de saída, R$0,01/GiB de entrada
- Suporte em português → respondem em minutos
Custos Reais (3 meses de uso)
Meu uso pessoal:
- 5 GB de documentos (≈4,66 GiB)
- ~1000 requisições/mês
Fatura mensal: ≈R$0,50/mês 🤯
Compare com:
- PostgreSQL gerenciado: R$50-200/mês
- MongoDB Atlas: R$80+/mês
- Heroku Postgres: $50/mês (~R$250)
Quando Usar
✅ Storage de documentos/comprovantes/arquivos
✅ Logs e eventos (time-series)
✅ Prototipagem rápida
✅ Side projects (custos baixos)
✅ Sistemas WORM (Write Once, Read Many)
✅ Dados não-relacionais (não precisa de joins)
Basicamente: se você está pensando em "salvar arquivos no servidor", considere S3 diretamente.
Lições Aprendidas
1. Simplicidade Vence
Gastei 5 horas construindo isso. Gastaria 5 semanas com PostgreSQL + migrations + ORM + backups + monitoramento.
2. Object Storage é Subestimado
Desenvolvedores pensam "S3 = arquivos grandes". Errado. S3 é key-value store distribuído com storage barato.
3. Nem Tudo Precisa de ACID
95% das minhas queries são:
- "Me dá esse arquivo"
- "Lista arquivos dessa categoria"
- "Deleta isso"
Nada disso precisa de transações complexas.
4. Prefixos = Índices Grátis
Organizar por categoria/subcategoria/arquivo é essencialmente criar índices.
despesas-mensais/2024/10/fatura.pdf
Isso me permite:
- Listar tudo de outubro:
Prefix="despesas-mensais/2024/10/" - Listar tudo de 2024:
Prefix="despesas-mensais/2024/" - Listar todas despesas:
Prefix="despesas-mensais/"
5. Infraestrutura Brasileira Importa
MagaluCloud com datacenter em SP = <50ms de latência.
AWS US East = 180ms de latência.
Para usuário final, isso é perceptível.
Conclusão
Construir NimbusVault me ensinou que nem sempre precisamos da solução mais complexa.
Antes:
- PostgreSQL (R$80/mês)
- Redis para cache (R$40/mês)
- VM com 2GB RAM (R$60/mês)
- Total: R$180/mês
Agora:
- MagaluCloud Object Storage (~R$1/mês)
- Total: R$1/mês
Economia: R$2.148/ano 💰
E o melhor: menos coisas para quebrar.
Não preciso me preocupar com:
- Backups (S3 é 11 noves de durabilidade)
- Escalabilidade (S3 escala infinito)
- Manutenção (zero administração)
- Atualizações (API não muda)
Código Aberto
Todo o código está no GitHub:
github.com/mcruvinel/NimbusVault
Sinta-se livre para:
- ⭐ Dar uma estrela
- 🍴 Fazer fork
- 🐛 Reportar bugs
- 💡 Sugerir features
Experimente Você Mesmo
# 1. Clone
git clone https://github.com/mcruvinel/NimbusVault
cd NimbusVault
# 2. Configure
cp .env.example .env
# Edite .env com suas credenciais MagaluCloud
# 3. Run
docker compose up -d
# 4. Acesse
open http://localhost:8080
Como obter credenciais:
- Acesse console.magalu.cloud
- Crie um bucket em Object Storage
- Gere um par de chaves de acesso
Pensamentos Finais
Este projeto começou como um experimento de fim de semana e virou minha solução real de gestão financeira.
Prova que ferramentas simples, usadas criativamente, resolvem problemas complexos.
Às vezes, você só precisa de um bucket bem organizado.
Gostou? Compartilhe este post!
- GitHub: @mcruvinel
- Blog: mount.log
Documentação MagaluCloud ObjectStorage
Tags: #Python #FastAPI #React #S3 #MagaluCloud #ObjectStorage #CloudStorage #FinTech #OpenSource #Serverless

Top comments (1)
Ideia incrivel, vou testar em breve!!