O principal problema de um sprint com time misto de front-end e back-end não é técnico — é de sequenciamento. O front precisa do contrato de API para construir a tela. O back precisa do wireframe para saber o que expor na API. Cada lado espera o outro. O sprint acaba com muito trabalho "quase pronto" e zero histórias entregues.
A solução não é separar os times (cada especialidade no seu silo). É criar as práticas que tornam front e back trabalhar em paralelo, com contratos explícitos e handoffs planejados.
O problema raiz: dependências ocultas no backlog
Em um backlog típico mal refinado, uma história como "como usuário, quero ver meu histórico de pedidos" esconde pelo menos três dependências entre front e back que ninguém mapeou: o endpoint de listagem com filtros e paginação, o formato do objeto de retorno (campos, tipos, tratamento de nulos), e os estados de loading/erro/vazio que o front precisa tratar.
Quando essas dependências só aparecem durante o desenvolvimento, o resultado é interrupção: o dev de front para o que está fazendo para esperar o back criar o endpoint, ou inventa uma estrutura de resposta que depois precisa ser refeita quando o back entrega algo diferente.
A solução começa no refinement: nenhuma história técnica entra no sprint sem ter o contrato de integração definido. Isso não significa implementado — significa acordado.
O contrato de API como artefato de planejamento
Antes de uma história entrar no sprint, front e back precisam concordar com o contrato da integração. Isso inclui: endpoints necessários (method + path), estrutura do request e response, códigos de status e formatos de erro, e qualquer comportamento específico de edge cases (o que acontece quando o usuário não tem pedidos? quando o filtro não retorna resultados?).
O formato mais eficiente para isso é uma spec OpenAPI mínima, escrita colaborativamente durante o refinement. Não precisa ser completa — precisa ser suficiente para que o front saiba o que esperar e para que o back saiba o que entregar:
# Exemplo de contrato mínimo acordado no refinement
# Não é a documentação final — é o acordo de sprint
GET /api/orders?page=1&pageSize=10&status=completed
Response 200:
{
"items": [
{
"id": "uuid",
"createdAt": "ISO 8601",
"total": 150.00,
"status": "completed",
"itemCount": 3
}
],
"page": 1,
"pageSize": 10,
"totalCount": 47,
"totalPages": 5
}
Response 401: { "error": "Unauthorized" }
Response 400: { "error": "string", "details": ["..."] }
# Edge cases acordados:
# - Sem pedidos: retorna items: [], totalCount: 0 (não é 404)
# - Filtro inválido: retorna 400 com mensagem no campo "error"
Com esse contrato acordado, front e back podem trabalhar em paralelo desde o primeiro dia do sprint.
Mock-first: front trabalha sem esperar o back
Com o contrato definido, o front não precisa esperar o back implementar o endpoint para desenvolver a tela. Usa um mock local que retorna a estrutura acordada e implementa toda a lógica de apresentação: estados de loading, tratamento de erro, paginação, filtros.
Existem duas abordagens comuns para mocks no front-end: dados hardcoded em um arquivo de fixture (simples, funciona para histórias sem muita variação de estado), ou um servidor mock local como MSW (Mock Service Worker) que intercepta as requisições HTTP e retorna os dados simulados. O MSW tem a vantagem de funcionar na camada de rede — o front se comporta exatamente como se estivesse falando com o back real, o que facilita a integração quando o back ficar pronto.
// Exemplo com MSW — handlers de mock para desenvolvimento
// src/mocks/handlers.ts
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/api/orders', ({ request }) => {
const url = new URL(request.url)
const page = Number(url.searchParams.get('page')) || 1
const status = url.searchParams.get('status')
// Simula o contrato acordado no refinement
return HttpResponse.json({
items: generateMockOrders(10, status),
page,
pageSize: 10,
totalCount: 47,
totalPages: 5
})
}),
// Simula erro para testar tratamento no front
http.get('/api/orders/error', () => {
return HttpResponse.json(
{ error: 'Internal Server Error' },
{ status: 500 }
)
})
]
// Ativado apenas em desenvolvimento
// src/main.tsx
if (import.meta.env.DEV) {
const { worker } = await import('./mocks/browser')
await worker.start()
}
Critérios de pronto para histórias com integração
Um dos maiores problemas de qualidade em times mistos é a história que vai para "Done" quando a parte de uma especialidade está pronta, mas a integração não foi validada. O back diz "endpoint feito e testado". O front diz "tela feita com mock". A história vai para done. Na demo, a tela não funciona com o endpoint real.
A solução é tornar explícito no Definition of Done de histórias com integração que a validação end-to-end é parte do critério de conclusão:
Definition of Done para histórias com integração front + back: a tela funciona contra o endpoint real (não mock) no ambiente de staging; estados de loading, erro e vazio foram testados com o endpoint real; a estrutura do response real foi validada contra o contrato acordado no refinement; o fluxo completo foi demonstrado para o PO antes de mover para Done.
Isso parece óbvio escrito assim, mas a maioria dos times não tem isso explícito — e as exceções viram regra.
Planejamento de capacidade com dois stacks no mesmo sprint
O erro mais comum no planning de times mistos é tratar a capacidade como um número único. "Temos 80 pontos de capacidade nesse sprint" — mas se 40 pontos são de histórias de front e 40 de back, a capacidade real depende do quanto front e back estão balanceados.
Na prática, poucas histórias são puramente de front ou puramente de back. A maioria tem trabalho nos dois lados. Durante o planning, para cada história com componente de integração, estime separadamente: quanto é front? Quanto é back? Uma história de "5 pontos" que na verdade são 2 de back (endpoint simples) e 8 de front (tela complexa com múltiplos estados) vai ter uma distribuição de carga muito diferente de uma história de "5 pontos" balanceada.
Se o time tem capacidade de 3 devs de front e 2 de back, e o sprint está planejado com 70% do trabalho do lado do back, alguém vai ficar parado ou sobrecarregado. Visualizar a carga por especialidade antes de fechar o sprint evita esse problema.
Handoffs explícitos: quando o trabalho muda de mão
Em histórias complexas, o trabalho não flui de uma vez só de um lado para outro. Há momentos em que o back precisa de algo do front para continuar, e vice-versa. Esses handoffs precisam ser planejados explicitamente — não descobertos quando alguém fica bloqueado.
Um exemplo de uma história de checkout: o back precisa dos campos do formulário de pagamento para definir o schema do request. O front precisa do contrato de request para construir o formulário. O back precisa do formato do erro de validação para construir os testes. O front precisa do formato do erro para mostrar o feedback ao usuário.
Mapear esses handoffs durante o refinement — quem entrega o quê, para quem, e em que ordem — transforma dependências ocultas em sequência planejada. Não elimina a interdependência, mas a torna gerenciável.
Standup com time misto: foco em bloqueios, não em status
O standup diário em times mistos tende a degenerar em atualização de status que cada pessoa escuta por educação enquanto espera sua vez. "Ontem fiz isso, hoje vou fazer aquilo, sem bloqueios" repetido oito vezes não cria valor.
O formato mais eficiente para times com interdependências: o standup é para as histórias, não para as pessoas. Para cada história em progresso: está no prazo? Há algum bloqueio? Alguém precisa de algo de outra pessoa para continuar? Quem passa o dia sem interação com as interdependências do sprint não precisa falar — pode fazer um rápido check-in assíncrono.
A pergunta que mais revela bloqueios reais: "tem alguma história que precisa de algo de outra pessoa para avançar?" Essa pergunta faz front e back falarem sobre as dependências do dia antes de ficarem travados esperando.
Review e demo com ambas as especialidades
A sprint review em times mistos tem um problema específico: quem demonstra o trabalho tende a ser quem tem mais visibilidade — geralmente o front, porque a tela é mais fácil de mostrar. O trabalho de back — endpoint com lógica complexa, validações, performance — fica invisível.
Isso cria um problema de reconhecimento e de qualidade. Trabalho de back que não é demonstrado não recebe feedback do PO e do negócio — o que significa que bugs de lógica de negócio no back podem passar despercebidos até chegarem em produção.
Reserve espaço na review para demonstrar o trabalho de back que merece visibilidade: um endpoint com regras de negócio complexas pode ser demonstrado via Swagger UI ou Postman, mostrando as validações, os casos de erro e o comportamento em edge cases. Isso não é detalhe técnico irrelevante para o negócio — é evidência de que as regras de negócio foram implementadas corretamente.
Retrospectiva com foco nas integrações
A retro de times mistos frequentemente captura problemas superficiais ("comunicação poderia ser melhor") sem chegar nas causas raiz. Para times com desafios de integração front/back, vale ter perguntas específicas:
Quais histórias foram bloqueadas por dependências entre front e back? Essas dependências estavam mapeadas no planning? O contrato de API acordado no refinement foi seguido, ou mudou durante o desenvolvimento? O que mudou e por quê? Quais histórias foram para "Done" sem validação de integração real? O que precisamos mudar no nosso processo de refinement para ter contratos mais claros no próximo sprint?
Retrospectivar sobre as integrações especificamente, e não sobre o processo em geral, produz ações muito mais concretas e implementáveis.
Quando separar times por especialidade faz sentido
Times mistos de front e back funcionam bem quando as histórias têm componentes nas duas especialidades (o que é o caso da maioria das features de produto). Mas há contextos onde separar faz mais sentido: trabalho puramente de infraestrutura ou plataforma (sem componente visual), migração de dados ou sistemas legados sem interface, ou quando o time é grande o suficiente para que as interdependências criem mais coordenação do que valor.
A decisão deve ser baseada nas interdependências reais do trabalho, não em preferências ou silos organizacionais. Um time misto mal sincronizado entrega menos do que dois times separados bem organizados. Um time misto bem sincronizado entrega mais do que qualquer configuração separada porque elimina os handoffs entre equipes.
Sincronizar times mistos de front e back é um desafio de processo e cultura, não só de ferramentas. Se você quer melhorar a eficiência de entrega do seu time de desenvolvimento, a Neryx pode ajudar com um diagnóstico e plano de melhoria.