Como o ClickHouse escalou o PgBouncer para quadruplicar a vazão no Postgres
Com so_reuseport e peering, ClickHouse Managed Postgres supera gargalo de thread única do PgBouncer, elevando a vazão para 336k transações por segundo.
Evan Hahn defende o uso do modificador STRICT no SQLite para evitar erros silenciosos de tipagem de dados e garantir a consistência do banco.
No dia 11 de julho de 2026, o experiente desenvolvedor Evan Hahn compartilhou um estudo técnico defendendo uma mudança importante na forma como equipes de engenharia de software lidam com bancos de dados relacionais leves. O foco central do artigo é a recomendação de uso das tabelas estritas (strict tables) no SQLite. Trata-se de uma funcionalidade adicionada a partir da versão 3.37.0 do motor de banco de dados, lançada originalmente em novembro de 2021. De acordo com Hahn, a tipagem rígida proporcionada por esse recurso ajuda a evitar problemas graves de inconsistência, impedindo, por exemplo, a gravação acidental de textos em colunas estruturadas para números.
Para transformar uma tabela comum do SQLite em uma estrutura de dados estrita, a modificação exigida na sintaxe é extremamente simples e direta. O desenvolvedor precisa apenas incluir a palavra-chave STRICT ao final da instrução de definição da tabela. Em seu exemplo de código prático, Hahn contrasta o modelo de criação de tabela tradicional com a nova abordagem estrita para evidenciar a sutil diferença na instrução do esquema de banco de dados:
Essa modificação sintática aparentemente discreta altera profundamente o comportamento interno do motor do SQLite. Com a regra de validação ativa, o sistema passa a validar rigidamente os tipos declarados antes de persistir qualquer informação no disco rígido, eliminando a antiga permissividade dinâmica do sistema.
A maior vantagem prática de utilizar tabelas estritas reside na prevenção ativa de incompatibilidades de tipos de dados durante as operações de gravação (INSERT) e atualização (UPDATE). Por padrão, o SQLite adota um sistema de tipos altamente permissivo e flexível. Em uma tabela convencional, sem a diretiva STRICT, o banco aceita qualquer tipo de informação em qualquer coluna. Se o programador tentar gravar uma string de texto qualquer em uma coluna configurada para números inteiros, o banco salvará o dado sem emitir nenhum tipo de aviso ou erro de integridade.
Para ilustrar essa situação de risco técnico, Evan Hahn construiu um cenário com uma tabela não estrita chamada people_nonstrict contendo uma coluna para idade configurada como inteiro:
CREATE TABLE people_nonstrict (age INTEGER);
INSERT INTO people_nonstrict (age) VALUES ('garbage');
No modelo tradicional do banco, o comando acima é concluído com absoluto sucesso, inserindo o texto literal 'garbage' (lixo) no lugar reservado para um número inteiro. No entanto, ao aplicar a palavra-chave STRICT em uma tabela equivalente chamada people_strict, a mesma instrução de inserção falha de forma ruidosa e retorna uma mensagem de erro explícita ao desenvolvedor:
CREATE TABLE people_strict (age INTEGER) STRICT;
INSERT INTO people_strict (age) VALUES ('garbage');
-- Erro retornado: cannot store TEXT value in INTEGER column
Conforme argumentado por Hahn em seu artigo técnico, tentar inserir valores de texto em uma coluna configurada estritamente como INTEGER representa um erro técnico que não deve ser tolerado de forma silenciosa pelo banco de dados. O mesmo rigor de validação de dados ocorre durante as operações de UPDATE, evitando que registros existentes sejam corrompidos posteriormente por dados inadequados vindos da aplicação.
Apesar da rigidez imposta pela diretiva STRICT, o SQLite mantém uma mecânica inteligente e segura de coerção de dados conhecida como conversão sem perdas (lossless conversion). Isso significa que, se um valor de um tipo diferente puder ser convertido perfeitamente e sem distorções para o tipo de dados definido na coluna, o banco ainda permitirá a gravação do registro.
Por exemplo, a string de texto '123' pode ser convertida sem qualquer perda de precisão ou integridade no número inteiro 123. Hahn demonstra que, mesmo em uma tabela estrita, as duas linhas de instrução listadas abaixo são consideradas equivalentes e serão aceitas normalmente pelo validador:
INSERT INTO people_strict (age) VALUES ('123');
INSERT INTO people_strict (age) VALUES (123);
Essa abordagem híbrida garante que sistemas que lidam com entradas de formulários web, requisições de APIs ou payloads que trafegam dados em formato de texto ainda consigam interagir com o banco de dados sem a obrigatoriedade de realizar conversões manuais e exaustivas de tipos no código-fonte da aplicação antes de cada escrita.
Outro problema histórico do comportamento permissivo do SQLite é a possibilidade de criar colunas utilizando tipos de dados completamente fictícios ou incorretos durante a modelagem inicial do banco de dados. No modo convencional, o motor do banco aceita qualquer termo no campo de tipo de coluna, mesmo que ele não corresponda a um formato suportado pelo motor. Evan Hahn aponta que declarações com tipos inválidos como os listados abaixo são aceitas sem erros na configuração padrão:
CREATE TABLE tbl (name GARBAGE);
CREATE TABLE tbl (name DATETIME);
CREATE TABLE tbl (name JSON);
CREATE TABLE tbl (name UUID);
CREATE TABLE tbl (name BLOBB);
Declarações como BLOBB (com um erro ortográfico óbvio) ou tipos comuns em outros motores mas não suportados nativamente no SQLite (como UUID ou JSON) são toleradas de forma passiva pelo sistema. Ao utilizar a palavra-chave STRICT na declaração da tabela, o motor passa a validar os tipos e rejeitará imediatamente qualquer instrução contendo definições de dados fora do conjunto oficial de tipos válidos.
Com a regra de tabela estrita ativada, o banco aceitará estritamente as seguintes opções de tipo de coluna:
Adicionalmente, a regra de tabelas estritas exige que todas as colunas possuam um tipo de dados associado de forma obrigatória. Por conta disso, instruções genéricas e sem tipo definido, como por exemplo CREATE TABLE tbl (name), também passarão a emitir alertas de erro imediatos, impedindo a criação de esquemas vagos.
Para cenários de modelagem de dados nos quais a flexibilidade total de gravação ainda se faz necessária em colunas específicas, o SQLite disponibiliza o tipo de dado especial chamado de ANY. Como a nomenclatura indica, esse tipo permite que valores de absolutamente qualquer categoria de dado sejam salvos na coluna correspondente, mesmo que a tabela esteja operando sob a diretiva rígida de validação STRICT.
No artigo original de 2026, Hahn exemplifica o uso desse recurso criando uma tabela estrita que utiliza a flexibilidade do tipo genérico:
CREATE TABLE tbl (value ANY) STRICT;
A partir dessa modelagem, o motor de banco de dados passa a aceitar gravações heterogêneas sem disparar restrições de tipo de dados. Todas as instruções abaixo tornam-se perfeitamente aceitáveis:
INSERT INTO tbl (value) VALUES (123);
INSERT INTO tbl (value) VALUES ('text');
INSERT INTO tbl (value) VALUES (12.34);
INSERT INTO tbl (value) VALUES (X'8647');
Embora o desenvolvedor Evan Hahn relate que pessoalmente ainda não identificou um caso prático ou necessidade real de aplicar o tipo ANY em seus fluxos de trabalho do dia a dia, ele reconhece que o recurso oferece uma alternativa de flexibilidade controlada para outros desenvolvedores que necessitarem desse comportamento específico.
Embora a tipagem rígida ofereça grandes vantagens de segurança de código, a migração de bases de dados legadas para o novo padrão estrito apresenta desafios técnicos relevantes. O principal entrave na arquitetura do SQLite é a impossibilidade de executar um comando simplificado de alteração como ALTER TABLE para injetar a diretiva de validação em uma tabela dinâmica já existente no sistema.
Dessa forma, para converter um esquema antigo no modelo estrito, o desenvolvedor precisa adotar uma estratégia em múltiplas etapas, que consiste em recriar a tabela e migrar os dados manualmente por meio de comandos estruturados:
Hahn detalha a sequência necessária de comandos de banco de dados para consolidar a transição com segurança no código abaixo:
CREATE TABLE new_people (name TEXT) STRICT;
INSERT INTO new_people SELECT * FROM people;
DROP TABLE people;
ALTER TABLE new_people RENAME TO people;
Esse processo de cópia e renomeação exige cuidados operacionais. Caso a tabela não estrita original contenha dados corrompidos ou tipos incompatíveis inseridos ao longo do tempo (como um texto em uma coluna numérica), a tentativa de migração utilizando a instrução de seleção INSERT INTO new_people SELECT * FROM people; será bloqueada e falhará imediatamente devido às novas regras de validação aplicadas na tabela de destino. Para contornar esse problema, o desenvolvedor precisará realizar uma limpeza prévia na base ou aplicar funções de coerção de tipo nas consultas.
Outra possibilidade aventada é adotar a política de tipagem estrita apenas para as tabelas criadas a partir do momento de adoção da regra, deixando as tabelas antigas em seu formato padrão. Hahn adverte que, embora viável, essa postura híbrida pode causar inconsistências na validação de dados dentro da base e surpreender os desenvolvedores, tornando a decisão de adotá-la algo que depende da análise de cada equipe de engenharia.
Apesar de o autor do artigo declarar sua clara preferência por tabelas que impõem restrições duras ao tipo de dado, os próprios engenheiros responsáveis pelo desenvolvimento do core do SQLite defendem publicamente uma visão oposta. O portal do projeto conta com um artigo oficial de documentação intitulado "The Advantages Of Flexible Typing" (As Vantagens da Tipagem Flexível), que reúne uma série de defesas técnicas sobre o comportamento tradicional dinâmico.
Evan Hahn relata que, embora discorde dessa perspectiva flexível para a maioria dos casos práticos devido aos riscos de surgimento de bugs silenciosos, os desenvolvedores do SQLite apontam cenários úteis onde a tipagem dinâmica oferece vantagens concretas. Entre os principais cenários favoráveis à tipagem dinâmica destacados na documentação estão:
Curiosamente, Hahn aponta que existe um aparente conflito interno no desenvolvimento do banco. O autor localizou um comentário no código-fonte do próprio SQLite no qual a tipagem flexível tradicional das tabelas não estritas é rotulada e tratada formalmente como recurso de legado (legacy), mesmo que os criadores mantenham a preferência pelo dinamismo nos textos oficiais de documentação do banco de dados.
A adoção das tabelas estritas exige atenção redobrada aos ambientes onde o banco de dados é executado. A diretiva de validação de tipos não existia em versões do software lançadas antes de novembro de 2021, época em que o suporte às tabelas estritas foi oficialmente introduzido a partir do SQLite 3.37.0.
Essa dependência cronológica cria uma barreira importante de retrocompatibilidade. Caso um arquivo de banco de dados seja criado ou alterado para conter uma tabela estrita e, posteriormente, esse mesmo arquivo precise ser lido ou modificado por um sistema rodando uma versão anterior da biblioteca — como o SQLite 3.36.0 —, o motor legado retornará um erro estrutural imediato. O erro de leitura ocorrerá mesmo que a tabela estrita já esteja criada e persistida fisicamente no arquivo de banco de dados, inviabilizando a portabilidade direta dos arquivos com versões mais antigas do ecossistema.
Do ponto de vista puramente teórico da engenharia de software, a adição de verificações de consistência e validação de tipos de dados durante as fases de escrita (INSERT) e edição (UPDATE) introduz etapas de processamento que poderiam reduzir a velocidade geral das transações do sistema.
Com o objetivo de validar o impacto real dessa penalidade de desempenho, Evan Hahn desenvolveu um script de teste para forçar e estressar o motor do banco de dados. O script realizou a inserção de milhões de linhas de dados em tabelas configuradas com 100 colunas distintas, rodando o mesmo experimento comparativo em múltiplos computadores de diferentes especificações de hardware.
O resultado do teste de estresse revelou fatos importantes sobre o comportamento prático do recurso:
Hahn salienta ainda que a tipagem estrita pode potencialmente oferecer uma melhora no desempenho de longo prazo da aplicação. Isso decorre do fato de que o desenvolvedor, ao ser forçado a usar os tipos corretos, evita conflitos ou incompatibilidades com as afinidades de coluna (column affinities) internas do SQLite, otimizando caminhos de leitura e indexação no banco de dados.
Em sua análise final, Evan Hahn conclui que as vantagens trazidas pela adoção do modificador STRICT no SQLite superam significativamente as desvantagens de compatibilidade ou o trabalho adicional exigido na migração de dados de esquemas antigos. A imposição de tipos rígidos funciona como uma camada extra de segurança silenciosa, eliminando erros ocultos de digitação e formatação de variáveis diretamente na raiz da persistência de dados.
Para o desenvolvedor, manter a estrutura sob rígida validação de dados promove a sanidade e a longevidade de sistemas complexos. Embora não atue como uma cura milagrosa para todos os desafios e anomalias de dados que ocorrem na engenharia de software, o uso do modificador de tabelas estritas é uma técnica de simples implementação que fornece uma base sólida de consistência para qualquer projeto tecnológico fundamentado no ecossistema de bancos de dados do SQLite.
Com so_reuseport e peering, ClickHouse Managed Postgres supera gargalo de thread única do PgBouncer, elevando a vazão para 336k transações por segundo.
A remadora Kelsey Pfendler completou a rota da Califórnia ao Havaí em menos de 44 dias, superando as marcas históricas feminina e masculina.
Apple abre processo contra OpenAI apontando roubo de segredos industriais por ex-funcionários, detalhando CADs e protótipos desviados.