> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrações de banco de dados

> Rode as migrações de esquema PostgreSQL do Midaz Ledger e do Tracer com imagens dedicadas de runner, para que as aplicações subam contra um banco de dados já migrado.

O Midaz aplica migrações de esquema PostgreSQL por meio de imagens dedicadas de runner (uma para o Ledger, uma para o Tracer), desacopladas dos binários da aplicação. As aplicações não migram mais na inicialização. Elas sobem contra um esquema que o runner já migrou.

<Note>
  Esse modelo é o que roda sob `make up` no desenvolvimento local e sob o Helm chart no Kubernetes. Se você usa `make up`, não precisa de nenhuma etapa manual. O compose trava a aplicação no runner de migração.
</Note>

## Por que um runner dedicado

***

O antigo migrador embutido no processo rodava a cada inicialização da aplicação, a partir do diretório de trabalho. Sob um contexto de segurança de pod reforçado (`distroless:nonroot`, `runAsUser: 1000`, `readOnlyRootFilesystem: true`, `capabilities: drop [ALL]`), esse caminho falhava com `permission denied` e entrava em crash loop no pod.

O runner dedicado evita isso:

* As migrações rodam uma vez, como uma etapa separada, antes de a aplicação iniciar.
* A imagem da aplicação não inclui mais o SQL de migração e nunca escreve no esquema.
* A própria imagem do runner roda sem problemas sob o mesmo contexto de segurança reforçado (veja [Postura de segurança](#security-posture)).

## Imagens do runner

***

Cada release inclui duas imagens:

| Imagem                    | Aplica-se a                                     | Bancos de dados                   |
| ------------------------- | ----------------------------------------------- | --------------------------------- |
| `midaz-ledger-migrations` | Migrações de onboarding e transaction do Ledger | Dois: `onboarding`, `transaction` |
| `midaz-tracer-migrations` | Esquema do Tracer                               | Um                                |

As duas imagens compartilham a mesma estrutura:

* Base: [`migrate/migrate`](https://github.com/golang-migrate/migrate) `v4.19.1` (fixada).
* Roda como `USER 65532:65532` (non-root, independente de UID).
* Entrypoint em shell POSIX que monta uma DSN a partir de variáveis de ambiente, executa `migrate ... up` e encerra.
* Não escreve nada em disco. O Postgres controla o progresso das migrações na tabela `schema_migrations`, então `readOnlyRootFilesystem: true` é seguro.

O runner do Ledger aplica onboarding primeiro, depois transaction, em uma única invocação. O runner do Tracer aplica seu único banco de dados em uma única passagem.

## Contrato de ambiente

***

Cada entrypoint aceita um override de URL pronto ou as variáveis individuais `DB_*`. O override de URL tem precedência quando definido.

### Runner do Ledger

| Banco de dados | Override de URL            | Montada a partir de                                                                                                                                                          |
| -------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| onboarding     | `ONBOARDING_DATABASE_URL`  | `DB_ONBOARDING_HOST`, `DB_ONBOARDING_PORT` (padrão `5432`), `DB_ONBOARDING_USER`, `DB_ONBOARDING_PASSWORD`, `DB_ONBOARDING_NAME`, `DB_ONBOARDING_SSLMODE` (padrão `disable`) |
| transaction    | `TRANSACTION_DATABASE_URL` | `DB_TRANSACTION_*` (mesmo formato)                                                                                                                                           |

### Runner do Tracer

| Override de URL | Montada a partir de                                                                                         |
| --------------- | ----------------------------------------------------------------------------------------------------------- |
| `DATABASE_URL`  | `DB_HOST`, `DB_PORT` (padrão `5432`), `DB_USER`, `DB_PASSWORD`, `DB_NAME`, `DB_SSL_MODE` (padrão `disable`) |

### Formato da DSN

Quando o entrypoint monta a DSN a partir das variáveis `DB_*`, ele produz:

```text theme={null}
postgres://<user>:<encoded-password>@<host>:<port>/<name>?sslmode=<sslmode>
```

A senha é codificada em percent-encoding para que caracteres reservados de URI (`% @ : / ? # & + space [ ]`) não quebrem a DSN. O `%` é codificado primeiro para que escapes já inseridos não sejam codificados duas vezes.

O entrypoint registra apenas marcadores de fase (`applying onboarding migrations`, `applying transaction migrations`, `applying tracer migrations`, `migrations complete`). Ele nunca imprime credenciais nem a DSN montada.

## Desenvolvimento local

***

### `make up`

A partir da raiz do repositório, `make up`:

1. Inicia a infraestrutura e aguarda até que o Postgres esteja saudável.
2. Inicia os serviços de compose `ledger-migrate` e `tracer-migrate`, que rodam uma única vez.
3. Inicia cada serviço de aplicação, que usa `depends_on` para seu serviço de migração com `condition: service_completed_successfully`.

A aplicação nunca inicia contra um banco de dados não migrado.

### Targets de `make` no host

Cada componente expõe targets de Make no host, que rodam migrações diretamente contra um banco de dados local, por exemplo quando você desenvolve uma nova migração. Os targets usam a CLI fixa do `golang-migrate` e leem as configurações de conexão de `.env`.

Ledger (`components/ledger`):

| Target                     | Efeito                                            |
| -------------------------- | ------------------------------------------------- |
| `make migrate`             | Aplica onboarding e depois transaction (agregado) |
| `make migrate-onboarding`  | Aplica apenas onboarding                          |
| `make migrate-transaction` | Aplica apenas transaction                         |
| `make migrate-down`        | Reverte os dois bancos de dados                   |

Tracer (`components/tracer`):

| Target                 | Efeito                                                             |
| ---------------------- | ------------------------------------------------------------------ |
| `make migrate`         | Aplica o esquema do tracer                                         |
| `make migrate-down`    | Reverte o esquema do tracer                                        |
| `make migrate-version` | Exibe a versão atual do esquema                                    |
| `make migrate-force`   | Força a versão do esquema (recuperação de um estado inconsistente) |

### Exemplo: rodar o runner do Ledger manualmente

Raramente você precisa invocar a imagem do runner manualmente, porque o travamento do compose faz isso por você. Quando precisar, aponte o runner para seus bancos de dados via `DB_*` (ou `*_DATABASE_URL`) e rode uma vez:

```bash theme={null}
docker run --rm \
  --network=infra-network \
  -e DB_ONBOARDING_HOST=postgres \
  -e DB_ONBOARDING_PORT=5432 \
  -e DB_ONBOARDING_USER=midaz \
  -e DB_ONBOARDING_PASSWORD='s3cret!' \
  -e DB_ONBOARDING_NAME=onboarding \
  -e DB_ONBOARDING_SSLMODE=disable \
  -e DB_TRANSACTION_HOST=postgres \
  -e DB_TRANSACTION_PORT=5432 \
  -e DB_TRANSACTION_USER=midaz \
  -e DB_TRANSACTION_PASSWORD='s3cret!' \
  -e DB_TRANSACTION_NAME=transaction \
  -e DB_TRANSACTION_SSLMODE=disable \
  lerianstudio/midaz-ledger-migrations:<tag>
```

O runner sai com `0` em caso de sucesso (incluindo o caso idempotente de no-op) e com código diferente de zero em caso de falha.

## Deploy no Kubernetes

***

Em produção, rode cada runner de migração como um Job do Kubernetes (normalmente um PreSync Job do Argo CD ou um hook do Helm) que é concluído antes do rollout da aplicação. O Helm chart já configura isso para você. As seções abaixo cobrem as propriedades que importam se você criar seus próprios manifestos.

<Note>
  Para deploys multi-tenant, o runner é intencionalmente independente de tenant: ele migra os bancos de dados apontados pelo seu ambiente, uma vez. O fan-out por tenant é uma responsabilidade do deploy. Rode o Job uma vez por banco de dados de tenant, com os valores de `DB_*` (ou override de URL) daquele tenant.
</Note>

<h3 id="security-posture">
  Postura de segurança
</h3>

O runner funciona sob um contexto de segurança de pod reforçado:

* **Non-root**: a imagem define `USER 65532:65532`.
* **Independente de UID**: os arquivos de migração pertencem ao root e têm permissão de leitura para todos, então qualquer UID pode lê-los.
* **Seguro para `readOnlyRootFilesystem`**: o `migrate` não escreve nenhum estado no sistema de arquivos.

A mesma imagem roda sem problemas sob `runAsNonRoot: true`, `readOnlyRootFilesystem: true` e `capabilities: drop [ALL]`.

### TLS

Os entrypoints respeitam o `sslmode` definido no ambiente (`DB_ONBOARDING_SSLMODE`, `DB_TRANSACTION_SSLMODE` ou `DB_SSL_MODE`), com padrão `disable`. Recomenda-se que deploys de produção definam `require` (ou algo mais restritivo). O runner em shell não reproduz a aplicação de TLS em código, a classificação de erros ou a telemetria que as aplicações usam para suas próprias conexões. Você controla o TLS das migrações apenas por meio do `sslmode`, em troca de um runner mínimo e sem dependências.

## Convenções e idempotência

***

* **Pareadas up/down**: cada migração tem um arquivo `.up.sql` e um `.down.sql`.
* **Idempotente**: rodar `migrate up` quando o esquema já está na versão mais recente é um no-op. Rodar o runner novamente após uma aplicação parcial ou completa é seguro.
* **CLI fixa**: as imagens do runner e os targets `make` do host fixam todos o `golang-migrate` na versão `v4.19.1`.

## Atualizando a partir de versões anteriores

***

Você não precisa de nenhuma migração manual de dados ao atualizar a partir de uma versão do Midaz em que a aplicação migrava na inicialização. O esquema em disco é o mesmo. Para adotar o novo modelo:

1. Baixe o release que inclui as imagens do runner.
2. No Kubernetes, adicione os Jobs `midaz-ledger-migrations` e `midaz-tracer-migrations` ao seu pipeline de deploy para que rodem antes do rollout da aplicação. Se você usa o Helm chart oficial, isso já é feito para você.
3. No desenvolvimento local, o `make up` continua funcionando como antes. O compose agora trava automaticamente as aplicações nos novos serviços de migração de execução única.

## Páginas relacionadas

***

* [Instalando o Midaz](/pt/products/midaz/midaz-setup): configuração local completa com `make up`.
* [Atualizando o Midaz](/pt/products/midaz/updating-midaz): fluxos de atualização para local e Helm.
* [Estratégias de deploy](/pt/products/midaz/deployment): visão geral do deploy BYOC.
* [Variáveis de ambiente do Tracer](/pt/products/tracer/tracer-environment-variables): referência completa de configuração do Tracer.
