Pular para o conteúdo

Design clássico · Sênior

Reserva de hotel (Booking/Airbnb)

Projeto de entrevista clássico. Pontos centrais: reservas e concorrência.

16 min de leitura · Conteúdo revisado em 22 de outubro de 2026

Resposta curta

Projeto de entrevista clássico. Pontos centrais: reservas e concorrência. O exercício clássico pede o sistema de reservas de uma rede de hotéis: mostrar a página do hotel e a de detalhe do quarto, reservar um quarto, cancelar e administrar os dados dos hotéis.

01 · CONTEXTO

Pouca vazão, muita disputa

O exercício clássico pede o sistema de reservas de uma rede de hotéis: mostrar a página do hotel e a de detalhe do quarto, reservar um quarto, cancelar e administrar os dados dos hotéis. O cliente paga o valor integral no momento da reserva, e a busca de hotéis fica fora do escopo. Há ainda um requisito de negócio que complica o estoque: a rede aceita overbooking de dez por cento, isto é, vender mais quartos do que existem, na expectativa de que alguns clientes cancelem.

A escala de referência é uma rede com cinco mil hotéis e um milhão de quartos, com 70% de ocupação e estadia média de três dias. Isso dá cerca de 240.000 reservas por dia, ou algo como três reservas por segundo. Descendo o funil, a página de confirmação recebe cerca de 30 consultas por segundo e a de detalhe, cerca de 300.

O requisito não funcional que pesa é a alta concorrência: em alta temporada ou em grandes eventos, hotéis populares recebem muitos clientes tentando reservar o mesmo quarto. A latência, por outro lado, é moderada: aceita-se que o sistema leve alguns segundos para processar uma reserva. Por isso este caso é, no fundo, um problema de escrita concorrente sobre um estoque pequeno.

02 · MODELO

Reservar um tipo de quarto, não um quarto

Uma decisão de modelagem muda todo o resto: a reserva é feita no nível do tipo de quarto, e não de um quarto específico. O cliente reserva, por exemplo, um quarto duplo de um hotel para certas datas, e o hotel atribui o quarto físico depois. A tabela de inventário guarda, por hotel e tipo de quarto, quantos quartos existem e quantos já foram reservados, com uma linha por data, o que torna simples consultar e atualizar um intervalo de datas. Cada reserva, por sua vez, percorre estados: pendente, paga, reembolsada, cancelada ou rejeitada. Veja a modelagem de dados em ação no fluxo abaixo.

  1. O cliente abre o site ou o aplicativo da rede; a requisição entra pela API do comerciante, que a encaminha ao serviço certo.

    Diagrama da arquitetura: Fluxo de reserva de hotel
    CLClientenavega
    NWAPI do comerciante
    CPServiço de hotéis
    DBCatálogo de hotéis
    CPServiço de reservas
    DBBanco de reservas e inventário
  2. As páginas de hotel e de quarto vêm do serviço de hotéis, que lê o catálogo. Esses dados mudam pouco e não disputam estoque.

    Diagrama da arquitetura: Fluxo de reserva de hotel
    CLCliente
    NWAPI do comerciante
    CPServiço de hotéis
    DBCatálogo de hotéisdados do hotel
    CPServiço de reservas
    DBBanco de reservas e inventário
  3. Ao escolher tipo de quarto e datas, o serviço de reservas gera um pedido pendente com um identificador único, que volta ao cliente para revisão.

    Diagrama da arquitetura: Fluxo de reserva de hotel
    CLCliente
    NWAPI do comerciante
    CPServiço de hotéis
    DBCatálogo de hotéis
    CPServiço de reservaspedido pendente
    DBBanco de reservas e inventário
  4. Ao confirmar, o serviço grava a reserva e atualiza o inventário no mesmo banco relacional, numa só transação.

    Diagrama da arquitetura: Fluxo de reserva de hotel
    CLCliente
    NWAPI do comerciante
    CPServiço de hotéis
    DBCatálogo de hotéis
    CPServiço de reservas
    DBBanco de reservas e inventárioinventário + reserva
  5. Se o cliente cancelar, a reserva muda de estado e a quantidade reservada do inventário diminui, devolvendo o quarto ao estoque.

    Diagrama da arquitetura: Fluxo de reserva de hotel
    CLCliente
    NWAPI do comerciante
    CPServiço de hotéis
    DBCatálogo de hotéis
    CPServiço de reservas
    DBBanco de reservas e inventárioquarto liberado

03 · DUPLO CLIQUE

O mesmo usuário pedindo duas vezes

A venda dupla tem duas origens diferentes. A primeira é o mesmo usuário enviando a reserva mais de uma vez, por exemplo clicando duas vezes no botão. A segunda é a disputa de vários usuários pelo mesmo quarto, tratada na próxima seção. Bloquear o botão no cliente ajuda, mas não é confiável: o usuário pode, por exemplo, desativar o JavaScript e contornar a checagem.

A defesa que vale é no servidor: uma API idempotente, que produz o mesmo resultado não importa quantas vezes seja chamada. No desenho do livro, o serviço de reservas gera um identificador único ao criar o pedido, o cliente o envia ao confirmar, e ele é a chave primária da tabela de reservas. Se o usuário clicar de novo, a segunda gravação viola a restrição de unicidade e nenhuma reserva duplicada nasce.

04 · ÚLTIMO QUARTO

Dois usuários, um quarto

Suponha que reste um único quarto e que o banco não use o nível de isolamento serializável. Duas transações leem o inventário, ambas concluem que ainda há vaga, e cada uma grava a sua reserva. Como as mudanças de uma transação só ficam visíveis às outras após o commit, a segunda ainda enxerga o estado antigo. O resultado é o sistema permitir que os dois usuários reservem, mesmo havendo apenas um quarto. Resolver isso exige, em geral, algum tipo de trava ou verificação na hora de gravar.

  1. Dois usuários pedem, quase ao mesmo tempo, o último quarto de um tipo, para as mesmas datas.

    Diagrama da arquitetura: Disputa pelo último quarto
    CLUsuário Aquer o quarto
    CLUsuário Bquer o quarto
    CPServiço de reservas
    DBBanco de inventário
  2. Cada transação lê o inventário e vê que ainda há um quarto livre. Nenhuma enxerga a outra, porque nada foi confirmado ainda.

    Diagrama da arquitetura: Disputa pelo último quarto
    CLUsuário A
    CLUsuário B
    CPServiço de reservas
    DBBanco de inventárioresta um
  3. Sem nenhuma proteção, as duas gravam a reserva e confirmam. O estoque diz que o quarto foi vendido, mas há dois hóspedes com direito a ele.

    Diagrama da arquitetura: Disputa pelo último quarto
    CLUsuário A
    CLUsuário B
    CPServiço de reservas
    DBBanco de inventáriovendeu duas vezes
  4. Com uma das proteções ativa, uma transação passa e a outra é recusada ou espera. O usuário recusado recebe um aviso de que o quarto acabou de ser vendido.

    Diagrama da arquitetura: Disputa pelo último quarto
    CLUsuário A
    CLUsuário Brecusado
    CPServiço de reservas
    DBBanco de inventárioprotegido

No bloqueio pessimista, a transação trava as linhas lidas, e as demais esperam até que ela termine. É simples e serializa as atualizações, mas pode causar deadlock quando vários recursos são travados e prejudica o desempenho quando as transações são longas. Por esses limites, o livro não o recomenda para este sistema.

No bloqueio otimista, uma coluna de versão acompanha a linha: ao gravar, a aplicação incrementa a versão e o banco confere se o novo valor é o esperado; se não for, a transação aborta. Sem contenção ele é mais rápido, porque nada fica travado. Sob contenção forte, só um dos clientes consegue gravar e os outros recebem falha de versão e precisam tentar de novo. Como a taxa de reservas costuma ser baixa, o livro o considera uma boa opção aqui.

A terceira opção é uma restrição no próprio banco, que rejeita qualquer estado em que o total reservado ultrapasse o inventário. É parecida com o otimista: fácil de implementar e adequada a pouca contenção, mas sob disputa forte gera muitas falhas. O livro a considera mais uma boa opção para o problema.

AbordagemComo evita a venda duplaLimite principal
Bloqueio pessimistaTrava as linhas lidas; as outras transações esperamDeadlocks e perda de desempenho com transações longas
Bloqueio otimistaColuna de versão; grava só se a versão não mudouMuitas novas tentativas quando há disputa forte
Restrição no bancoO banco recusa estoque reservado acima do inventárioMuitas falhas sob disputa forte; regra fora do controle de versão da aplicação

05 · ESCALA

E se fosse um site de viagens inteiro?

Uma pergunta de aprofundamento comum: e se o sistema atendesse não uma rede, mas um grande site de viagens, com uma carga mil vezes maior? Os serviços são sem estado e escalam adicionando servidores. O banco, que concentra todo o estado, é o gargalo e não escala só com mais instâncias.

A saída é o particionamento do banco. Como quase toda consulta filtra por hotel, a chave natural é o identificador do hotel: toda a história de um hotel vive no mesmo fragmento, e uma reserva toca um único banco. No exemplo do livro, com trinta mil consultas por segundo espalhadas por dezesseis fragmentos, cada um recebe cerca de 1.875 por segundo, dentro da capacidade de um servidor MySQL.

  1. A consulta de disponibilidade, de longe a operação mais frequente, é respondida pelo cache de inventário, sem tocar no banco.

    Diagrama da arquitetura: Reservas em escala: fragmentos e cache
    CLCliente
    NWAPI do comerciante
    CPServiço de reservas
    CHCache de inventárioconsulta de vagas
    DBFragmento A
    DBFragmento B
    CPCaptura de mudanças
  2. A reserva vai ao fragmento escolhido pelo hash do identificador do hotel e é validada pelo banco.

    Diagrama da arquitetura: Reservas em escala: fragmentos e cache
    CLCliente
    NWAPI do comerciante
    CPServiço de reservas
    CHCache de inventário
    DBFragmento Afragmento do hotel
    DBFragmento B
    CPCaptura de mudanças
  3. O banco é atualizado primeiro; um processo de captura de mudanças lê o que mudou e o envia ao cache de forma assíncrona.

    Diagrama da arquitetura: Reservas em escala: fragmentos e cache
    CLCliente
    NWAPI do comerciante
    CPServiço de reservas
    CHCache de inventário
    DBFragmento A
    DBFragmento B
    CPCaptura de mudançascaptura mudanças
  4. O cache converge para o estado do banco, depois de um pequeno intervalo.

    Diagrama da arquitetura: Reservas em escala: fragmentos e cache
    CLCliente
    NWAPI do comerciante
    CPServiço de reservas
    CHCache de inventárioatualizado
    DBFragmento A
    DBFragmento B
    CPCaptura de mudanças
  5. Nesse intervalo o cache pode mostrar um quarto que o banco já vendeu. A reserva chega ao banco, que faz a validação final e recusa; o usuário vê que o quarto acabou de ser vendido.

    Diagrama da arquitetura: Reservas em escala: fragmentos e cache
    CLCliente
    NWAPI do comerciante
    CPServiço de reservas
    CHCache de inventárioainda mostra vaga
    DBFragmento A
    DBFragmento B
    CPCaptura de mudanças

A leitura de inventário é uma ordem de grandeza mais frequente que a escrita, então um cache na frente do banco reduz muito a carga. O livro sugere o Redis, porque o TTL e o descarte do menos usado ajudam a aproveitar a memória. Mesmo quando o Redis mostra vaga, a reserva é conferida no banco, que é a fonte da verdade do estoque.

O custo é a consistência entre banco e cache. O banco é atualizado primeiro e a mudança segue para o cache de forma assíncrona, pelo código da aplicação ou por captura de mudanças (CDC), mecanismo que lê as alterações do banco e as aplica em outro sistema. A defasagem é aceitável, segundo o livro, desde que o banco faça a validação final do estoque.

06 · MICROSSERVIÇOS

Consistência entre serviços

Num monólito, várias operações cabem numa única transação do banco. Na arquitetura de microsserviços, cada serviço tem o seu banco, e uma operação logicamente atômica pode atravessar vários serviços; assim, não há uma transação única para garantir a consistência.

O livro cita duas saídas conhecidas para as transações distribuídas. O commit em duas fases (2PC) é bloqueante: a falha de um nó interrompe o progresso até ele voltar. Já a saga é uma sequência de transações locais; se um passo falha, executam-se transações compensatórias para desfazer os passos anteriores.

A escolha do livro para este problema foi pragmática: uma abordagem híbrida, em que o serviço de reservas cuida das APIs de reserva e de inventário, mantendo as duas tabelas no mesmo banco relacional e aproveitando as propriedades ACID. Decidir se a complexidade extra de distribuir vale a pena é, nas palavras do livro, uma escolha do arquiteto.

Perguntas frequentes

O que é Reserva de hotel (Booking/Airbnb)?

Projeto de entrevista clássico. Pontos centrais: reservas e concorrência.

O que o design de Reserva de hotel (Booking/Airbnb) cobre?

Ele está organizado nestas seções: Pouca vazão, muita disputa, Reservar um tipo de quarto, não um quarto, O mesmo usuário pedindo duas vezes, Dois usuários, um quarto, E se fosse um site de viagens inteiro? e Consistência entre serviços.

Quanto tempo leva Reserva de hotel (Booking/Airbnb) e qual é o nível?

Leva cerca de 16 minutos para ler e tem nível Sênior.

Agora projete você mesmo

Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.