EdTech Árabe Serverless: Scalabilidade com AWS Lambda
5 min de leituraMohammad Shaker

EdTech Árabe Serverless: Scalabilidade com AWS Lambda

Alphazed usa AWS Lambda para backend serverless com 95.000+ alunos, Flask, MySQL RDS e analytics customizado.

Engineering

Resposta rápida

Alphazed usa AWS Lambda para backend serverless com 95.000+ alunos, Flask, MySQL RDS e analytics customizado.

Escalando EdTech Árabe com AWS Lambda Serverless

A Alphazed roda todo seu backend — atendendo mais de 95.000 estudantes em mais de 50 países — usando AWS Lambda com Serverless Framework. A arquitetura utiliza Flask no Lambda por trás do API Gateway, MySQL 8 no RDS, S3 para entrega de conteúdo e um lago de dados analíticos customizado (SQS → Kinesis Firehose → S3 → Glue → Athena). Handlers finos no Lambda otimizam a latência do cold start, e o sistema suporta 7+ apps a partir de uma única base de código com configuração runtime dinâmica.

Por que Serverless para EdTech?

Apps educacionais têm padrões de uso imprevisíveis:

  • Manhãs de dias úteis: pais baixam o app antes de enviar filhos à escola (pico de tráfego)
  • Tardes de dias úteis: sessões de prática pós-escola (carga constante)
  • Finais de semana: sessões intensas (2-3x a carga normal)
  • Durante o Ramadã: uso noturno dispara (sessões familiares de Alcorão)
  • Férias escolares: padrão completamente diferente

Vantagens do Serverless:

  • Pagamento por requisição: paga-se só pelo uso real. Se 10 usuários acessam, paga-se 10 invocações. Se 100.000 durante evento viral, escala instantaneamente.
  • Sem cold start em endpoints de alta frequência: usamos camadas "sempre aquecidas" no Lambda para endpoints muito chamados.
  • Autoescalabilidade: atende de 10 a 10.000 usuários simultâneos sem mudanças infraestruturais.
  • Zero manutenção de servidores: a equipe foca no currículo e IA, não em clusters Kubernetes ou balanceadores.

Detalhes da Arquitetura

API Gateway → Lambda → RDS

[Client App] (iOS, Android, Web)
    ↓
[API Gateway] (roteamento HTTP, limitação de taxa)
    ↓
[Lambda Handlers] (app Flask, 512MB memória, timeout 28s)
    ├── Rotas do app: /app/* (endpoints mobile)
    ├── Rotas do usuário: /user/* (endpoints autenticados)
    └── Rotas admin: /boss/* (dashboard admin)
    ↓
[MySQL 8 no RDS] (dados persistentes)
    ↓
[Resposta] (JSON para o cliente)

Lambdas Finos para Velocidade

A maioria dos Lambdas são propositalmente minimalistas:

# Handler fino (~100KB)
import json
import pymysql

def get_user_progress(event, context): user_id = event['pathParameters']['user_id']

# Conexão direta ao DB (sem ORM)
conn = pymysql.connect(host='rds.aws.com', user='app', password='...', database='amal')
cursor = conn.cursor()
cursor.execute(
    'SELECT concept_id, accuracy FROM user_memory WHERE user_id = %s',
    (user_id,)
)
rows = cursor.fetchall()
conn.close()

return {
    'statusCode': 200,
    'body': json.dumps([{'concept': r[0], 'accuracy': r[1]} for r in rows])
}

Sem importação do Flask, sem ORM SQLAlchemy, sem middleware. Resultado: cold start de cerca de 500ms contra 5-10s para app Flask completo.

Endpoints pesados (geração de conteúdo, processamento analítico) usam Flask completo:

# Handler pesado (~30MB com Flask, SQLAlchemy, numpy)
from flask import Flask, jsonify
from models import UserMemory
import numpy as np

app = Flask(name)

@app.route('/content_duo/generate', methods=['POST']) def generate_content_duo(): # Lógica complexa usando ORM user = UserMemory.query.filter_by(user_id=request.json['user_id']).first() # ... gera sessão personalizada ... return jsonify(session_data)

Trade-off: cold starts mais lentos, mas chamados com menos frequência.

Prefixo por App nas Tabelas

Uma instância RDS serve 7+ apps com isolamento no nível de banco de dados:

-- App Amal
CREATE TABLE amal_users (...)
CREATE TABLE amal_content_bytes (...)
CREATE TABLE amal_user_memory (...)

-- App Thurayya CREATE TABLE thurayya_users (...) CREATE TABLE thurayya_content_bytes (...) CREATE TABLE thurayya_user_memory (...)

-- Outros apps: qais_, kidelite_, etc.

No deploy, variável de ambiente APP_NAME seleciona o prefixo:

app_name = os.getenv('APP_NAME', 'amal')  # 'amal', 'thurayya', 'qais', etc.

Queries usam prefixo dinamicamente

table_name = f'{app_name}_users' cursor.execute(f'SELECT * FROM {table_name} WHERE id = %s', (user_id,))

O Lago de Dados Analíticos

Problema: Consultas diretas para analytics atrasam produção, causando bloqueio de tabelas.

Solução: Pipeline analítico assíncrono

[App Mobile]
    ↓ (envia evento)
[API Endpoint] → [Fila SQS] (async)
    ↓ (responde imediatamente ao app)
    ↓ (não espera analytics)
[Kinesis Firehose] (agrega eventos a cada 5 min ou 100MB)
    ↓
[S3] (particionado: s3://analytics-lake/amal/2026/03/28/events.parquet)
    ↓
[AWS Glue] (rastrea S3, infere esquema)
    ↓
[Athena] (consultas SQL via motor Presto)
    ↓
[Dashboard] (mostra insights em tempo real)

Dead Letter Queue (DLQ)

Se ocorre falha analítica:

SQS → [Firehose falha]
  ↓
  [DLQ recebe mensagens falhadas]
  ↓
  [Alertas para equipe de operações]
  ↓
  [API de produção não afetada]

Analytics nunca bloqueia requisições do usuário. Crianças aprendem mesmo se pipeline analítico estiver fora.

Estratégias de Otimização de Custos

  • Lambdas finos para endpoints de alta frequência
    App típico chama API 10-20 vezes por sessão
    95.000 usuários ativos × 3 sessões/dia × 15 chamadas = 4,275M chamadas/dia
    Cada chamada custa ~$0,0000002 (Lambda), total ~$0,86/dia
    Reduzir 10s no cold start economiza ~$500/mês
  • Instâncias Reservadas RDS
    Reserva 3 anos: ~60% desconto comparado on-demand
    Usamos db.r6i.xlarge (4 vCPU, 32GB RAM): $2.800/mês reservado vs $6.500/mês on-demand
    Economia anual: ~$50.000
  • Cache
    Dados frequentes (currículo, conteúdo) em ElastiCache (Redis)
    Reduz consultas RDS em 70%
    Custos: $800/mês cache, economiza $2.000/mês no RDS

Servindo 7+ Apps numa única base de código

AppPrefixoTabelas DBStack LambdaStatus
Amalamal_40+ tabelasCompartilhadoProdução
Thurayyathurayya_40+ tabelasCompartilhadoProdução
Qaisqais_35+ tabelasCompartilhadoBeta
KidElitekidelite_40+ tabelasCompartilhadoProdução
Alphazed Schoolschool_50+ tabelasCompartilhadoBeta
Alphazed Montessorimontessori_45+ tabelasCompartilhadoInterno

Um backend, pipeline único, 6 apps simultâneos. Novo app em semanas, não meses.

Perguntas Frequentes

Q: Lambda não tem limite de 15 minutos?
A: Sim, mas raramente precisamos de requisições longas. Tarefas pesadas usam jobs assíncronos com SQS + Step Functions.

Q: E se o banco cair?
A: RDS tem failover Multi-AZ (primário + réplica standby). Failover automático em 60s. Clientes veem timeout breve, recuperação rápida.

Q: Como gerenciam pool de conexão em Lambda stateless?
A: Cada instância Lambda mantém pool reutilizado em invocações "quentes". Cold start cria conexões novas. RDS Proxy gerencia limite de conexões entre Lambda e RDS.

Artigos Relacionados