multi-clouds3gcsazuredata-lake

Um Data Lake, Três Nuvens: Analytics Multi-Cloud com DataSpoc

Michael San Martim · 2026-04-28

Sua empresa adquiriu uma startup que roda no GCP. Sua plataforma principal está na AWS. A equipe financeira armazena exports no Azure Blob Storage. Agora você precisa unir dados de clientes das três nuvens para um único relatório.

O DataSpoc Lens registra buckets do S3, GCS e Azure como um catálogo unificado. O DuckDB consulta todos eles com SQL padrão. Uma consulta, três nuvens, zero movimentação de dados.

O Cenário

Uma empresa de médio porte com dados espalhados entre provedores de nuvem:

NuvemBucketDadosEquipe
AWS S3s3://acme-productionDados core do app (usuários, pedidos)Engenharia
GCSgs://acme-acquired-appDados do produto adquiridoEx-equipe da startup
Azureaz://acme-financeExports financeiros, faturasFinanceiro

Cada equipe escolheu sua nuvem. Mover tudo para um único provedor é um projeto de 6 meses. Você precisa de analytics agora.

Passo 1: Registrar Todos os Buckets

Terminal window
# AWS S3 bucket
dataspoc-lens add-bucket s3://acme-production --name production
# Google Cloud Storage bucket
dataspoc-lens add-bucket gs://acme-acquired-app --name acquired
# Azure Blob Storage bucket
dataspoc-lens add-bucket az://acme-finance/data --name finance

Verifique que os três estão conectados:

Terminal window
dataspoc-lens tables
production.raw.users
production.raw.orders
production.raw.products
production.curated.daily_revenue
acquired.raw.app_users
acquired.raw.app_events
acquired.raw.subscriptions
finance.raw.invoices
finance.raw.payments
finance.raw.budget_forecast

Três nuvens, um catálogo.

Passo 2: Configurar Credenciais para Cada Provedor

AWS S3

Use um perfil AWS ou variáveis de ambiente:

Terminal window
# Option 1: AWS profile (recommended)
export AWS_PROFILE=production
# Option 2: Explicit credentials
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="..."
export AWS_REGION="us-east-1"

Ou use IAM roles se estiver rodando no EC2/ECS — nenhuma credencial necessária.

Google Cloud Storage

Use uma chave de service account ou credenciais padrão da aplicação:

Terminal window
# Option 1: Service account key
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
# Option 2: Application default credentials (if on GCP or gcloud configured)
gcloud auth application-default login

Azure Blob Storage

Use uma chave de storage account ou managed identity:

Terminal window
# Option 1: Storage account key
export AZURE_STORAGE_ACCOUNT="acmefinance"
export AZURE_STORAGE_KEY="..."
# Option 2: Connection string
export AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=..."
# Option 3: Managed identity (if running on Azure)
# No env vars needed -- uses Azure Instance Metadata

O DataSpoc Lens detecta o provedor pelo prefixo da URI do bucket (s3://, gs://, az://) e usa as credenciais correspondentes.

Passo 3: Consultas Cross-Cloud

Agora a parte interessante. Consulte dados de todas as três nuvens com uma única instrução SQL:

-- Match acquired app users with production users by email
SELECT
p.name AS production_name,
p.email,
p.plan AS production_plan,
a.subscription_tier AS acquired_plan,
a.last_active AS acquired_last_active,
f.total_invoiced
FROM production.raw.users p
JOIN acquired.raw.app_users a
ON LOWER(p.email) = LOWER(a.email)
LEFT JOIN (
SELECT customer_email, SUM(amount) AS total_invoiced
FROM finance.raw.invoices
GROUP BY customer_email
) f ON LOWER(p.email) = LOWER(f.customer_email)
ORDER BY f.total_invoiced DESC NULLS LAST
LIMIT 20;

Esta consulta faz join de dados AWS com dados GCS e dados Azure em uma única instrução. O DuckDB cuida das leituras cross-cloud de forma transparente.

Execute:

Terminal window
dataspoc-lens query "
SELECT
p.name, p.email, p.plan,
a.subscription_tier,
f.total_invoiced
FROM production.raw.users p
JOIN acquired.raw.app_users a ON LOWER(p.email) = LOWER(a.email)
LEFT JOIN (
SELECT customer_email, SUM(amount) AS total_invoiced
FROM finance.raw.invoices
GROUP BY customer_email
) f ON LOWER(p.email) = LOWER(f.customer_email)
ORDER BY f.total_invoiced DESC NULLS LAST
LIMIT 10
"
┌─────────────────┬──────────────────────┬────────┬───────────────────┬────────────────┐
│ name │ email │ plan │ subscription_tier │ total_invoiced │
├─────────────────┼──────────────────────┼────────┼───────────────────┼────────────────┤
│ Acme Corp │ admin@acme.com │ enterprise │ premium │ 125,400.00 │
│ TechFlow Inc │ ops@techflow.io │ business │ pro │ 89,200.00 │
│ Global Systems │ data@globalsys.com │ business │ premium │ 67,800.00 │
└─────────────────┴──────────────────────┴────────┴───────────────────┴────────────────┘

Passo 4: Cache para Performance

Consultas cross-cloud podem ser lentas porque dados são lidos pela rede de três provedores diferentes. O cache resolve isso:

Terminal window
# Cache the most-queried tables locally
dataspoc-lens cache refresh production.raw.users
dataspoc-lens cache refresh production.raw.orders
dataspoc-lens cache refresh acquired.raw.app_users
dataspoc-lens cache refresh finance.raw.invoices

Verifique o status do cache:

Terminal window
dataspoc-lens cache status
Table Status Size Last Refreshed
production.raw.users cached 1.2 MB 2 min ago
production.raw.orders cached 8.4 MB 2 min ago
acquired.raw.app_users cached 3.1 MB 1 min ago
finance.raw.invoices cached 5.6 MB 1 min ago
production.raw.products stale 42 KB 3 days ago
acquired.raw.app_events not cached -- --

Consultas em cache rodam contra arquivos Parquet locais — sem chamadas de rede, sem latência cross-cloud. O mesmo JOIN cross-cloud que levava 12 segundos sem cache roda em 200ms com cache.

Atualize caches desatualizados em um comando:

Terminal window
dataspoc-lens cache refresh-stale

Passo 5: Controle de Acesso por Bucket via IAM

O DataSpoc nunca implementa autenticação. O IAM de cada provedor de nuvem controla quem pode acessar o quê:

AWS S3 (production):
└── IAM Policy: DataEngineers group → full access
└── IAM Policy: Analysts group → read-only
GCS (acquired):
└── IAM Policy: IntegrationTeam → read-only
└── IAM Policy: AcquiredTeam → full access
Azure (finance):
└── IAM Policy: FinanceTeam → full access
└── IAM Policy: Executives → read-only

Quando um analista executa uma consulta que toca o bucket financeiro, ele precisa de credenciais Azure com acesso de leitura. Se não tiver, a consulta falha com um erro de permissão. O DataSpoc não tenta contornar o IAM da nuvem — ele respeita.

Exemplo Prático: Customer 360 Unificado

Construa uma visão completa do cliente cruzando as três nuvens:

-- transforms/01_customer_360.sql
CREATE OR REPLACE TABLE gold.customer_360 AS
WITH production_data AS (
SELECT
LOWER(email) AS email,
name,
plan AS production_plan,
created_at AS production_signup,
DATE_DIFF('day', created_at, CURRENT_DATE) AS days_as_customer
FROM production.raw.users
),
acquired_data AS (
SELECT
LOWER(email) AS email,
subscription_tier AS acquired_plan,
last_active AS acquired_last_active,
feature_usage_score
FROM acquired.raw.app_users
),
finance_data AS (
SELECT
LOWER(customer_email) AS email,
SUM(amount) AS total_invoiced,
COUNT(*) AS invoice_count,
MAX(invoice_date) AS last_invoice_date
FROM finance.raw.invoices
WHERE status = 'paid'
GROUP BY 1
),
order_data AS (
SELECT
LOWER(u.email) AS email,
COUNT(*) AS total_orders,
SUM(o.amount) AS total_revenue,
MAX(o.order_date) AS last_order_date
FROM production.raw.orders o
JOIN production.raw.users u ON o.user_id = u.user_id
WHERE o.status = 'completed'
GROUP BY 1
)
SELECT
p.email,
p.name,
p.production_plan,
p.production_signup,
p.days_as_customer,
a.acquired_plan,
a.acquired_last_active,
a.feature_usage_score,
f.total_invoiced,
f.invoice_count,
o.total_orders,
o.total_revenue,
o.last_order_date,
CASE
WHEN a.email IS NOT NULL THEN 'both_products'
ELSE 'production_only'
END AS product_usage,
COALESCE(o.total_revenue, 0) + COALESCE(f.total_invoiced, 0) AS total_ltv
FROM production_data p
LEFT JOIN acquired_data a ON p.email = a.email
LEFT JOIN finance_data f ON p.email = f.email
LEFT JOIN order_data o ON p.email = o.email;

Execute este transform:

Terminal window
dataspoc-lens transform run --file 01_customer_360.sql

Agora consulte a visão unificada:

Terminal window
dataspoc-lens query "
SELECT product_usage, COUNT(*) as customers, ROUND(AVG(total_ltv), 2) as avg_ltv
FROM gold.customer_360
GROUP BY product_usage
"
┌────────────────┬───────────┬──────────┐
│ product_usage │ customers │ avg_ltv │
├────────────────┼───────────┼──────────┤
│ both_products │ 2,340 │ 1,245.80 │
│ production_only│ 10,110 │ 342.50 │
└────────────────┴───────────┴──────────┘

Clientes usando ambos os produtos têm LTV 3,6x maior. Essa é uma oportunidade de cross-sell que você só poderia encontrar consultando entre nuvens.

Uso do SDK

A mesma configuração multi-cloud funciona a partir do Python:

from dataspoc_lens import LensClient
lens = LensClient()
# Tables from all clouds appear in one catalog
tables = lens.tables()
print(tables)
# ['production.raw.users', 'acquired.raw.app_users', 'finance.raw.invoices', ...]
# Cross-cloud query
result = lens.query("""
SELECT COUNT(DISTINCT p.email) AS overlap
FROM production.raw.users p
JOIN acquired.raw.app_users a ON LOWER(p.email) = LOWER(a.email)
""")
print(f"Users on both platforms: {result}")

Considerações de Custo

Transferência de dados cross-cloud custa dinheiro. Veja o que esperar:

TransferênciaCusto por GB
S3 para internet$0,09
GCS para internet$0,12
Azure para internet$0,087
Cache local (após primeira leitura)$0,00

Estratégia para minimizar custos:

  1. Cache agressivo — primeira consulta lê da nuvem, consultas subsequentes leem do cache local
  2. Refresh de cache agendadodataspoc-lens cache refresh-stale uma vez por hora
  3. Pré-agregar — construa tabelas gold que resumem dados cross-cloud, cache apenas as tabelas gold
  4. Filtre cedo — cláusulas WHERE no pushdown de Parquet reduzem bytes lidos

Para uma empresa com 10 GB em três nuvens, atualizar cache diariamente custa cerca de $3/mês em egress. Isso é mais barato que um único crédito Snowflake.

Um catálogo, três nuvens, zero movimentação de dados. Registre seus buckets, escreva SQL e deixe o DuckDB cuidar do resto.

Recomendados