Les fotos de MercadoFresco ja són a S3, amb el seu cicle de vida i el seu versionatge. Però el cor del
negoci continua al servidor de l'oficina: la base de dades de comandes. Allà hi ha els clients,
els productes, les cistelles, les rutes de repartiment i la facturació. És la dada que no es pot perdre,
la que no pot estar caiguda els divendres a les 19:00, i la que avui es desa amb un pg_dump a un
disc extern que ningú no ha provat mai de restaurar.
Aquesta lliçó migra aquesta base de dades a Amazon RDS (Relational Database Service), el servei gestionat de bases de dades relacionals d'AWS. No és només «PostgreSQL al núvol»: és delegar a AWS l'apedaçament, les còpies, la commutació per error i la replicació, tasques que a MercadoFresco ningú no feia perquè ningú no tenia temps. I amb les còpies automàtiques i la restauració a un punt en el temps tanquem definitivament el problema 2, la part que va quedar oberta a 02-02 quan vam resoldre les còpies dels discos però no les de les dades transaccionals.
Contingut
- Què és un servei gestionat i què deixa de ser problema teu
- RDS davant de PostgreSQL instal·lat en una EC2
- Motors disponibles i quin tria MercadoFresco
- Crear la instància RDS per consola
- Crear la instància RDS per CLI
- Multi-AZ: què és realment una rèplica síncrona en espera
- Rèpliques de lectura: els informes de la Sara sense castigar producció
- Còpies automàtiques, retenció i restauració a un punt en el temps
- Instantànies manuals i el tancament del problema 2
- Grups de paràmetres i finestres de manteniment
- Monitoratge: mètriques bàsiques i Performance Insights
- Connectar-se des de l'aplicació sense credencials al codi
- Escalat vertical i emmagatzematge autoescalable
- Migrar des del servidor de l'oficina
- Costos i com aturar una instància de proves
Què és un servei gestionat i què deixa de ser problema teu
Al servidor de l'oficina, PostgreSQL era responsabilitat íntegra de la Marta: instal·lar-lo, configurar-lo, actualitzar-lo, vigilar-lo, desar-ne còpies i aixecar-lo quan queia. A RDS, AWS assumeix una part concreta i ben delimitada d'aquesta feina.
| Tasca | Servidor de l'oficina | PostgreSQL en EC2 | Amazon RDS |
|---|---|---|---|
| Comprar i mantenir maquinari | Marta | AWS | AWS |
| Instal·lar el sistema operatiu | Marta | Tu | AWS |
| Apedaçar el sistema operatiu | Marta (mai) | Tu | AWS |
| Instal·lar PostgreSQL | Marta | Tu | AWS |
| Aplicar pedaços de PostgreSQL | Marta (mai) | Tu | AWS (a la finestra de manteniment) |
| Configurar còpies automàtiques | Marta (a mitges) | Tu | AWS |
| Provar la restauració | Ningú | Tu | AWS proporciona PITR |
| Muntar alta disponibilitat | Impossible | Tu (complexa) | AWS (una casella) |
| Commutació per error automàtica | No existeix | Tu | AWS (1-2 minuts) |
| Crear rèpliques de lectura | Molt laboriós | Tu | AWS (una comanda) |
| Xifratge en repòs | No | Tu | AWS (una casella) |
| Dissenyar l'esquema i les consultes | Marta i Luis | Tu | Tu |
| Optimitzar índexs | Marta i Luis | Tu | Tu |
| Seguretat de l'aplicació | Marta i Luis | Tu | Tu |
És el model de responsabilitat compartida de la lliçó 01-01 aplicat a un servei concret: la línia es mou cap amunt, però no desapareix mai. RDS no arreglarà una consulta sense índex ni dissenyarà les teves taules.
El que RDS no et deixa fer, i convé saber-ho abans de triar-lo:
- No hi ha accés al sistema operatiu. Res d'SSH a la màquina de la base de dades. Si la teva operativa depèn d'scripts al servidor, cal replantejar-la.
- No hi ha superusuari real. L'usuari mestre té el rol
rds_superuser, potent però limitat: no pot fer tot el que fa unsuperuserde PostgreSQL. - Les extensions estan en llista blanca. Només pots instal·lar les que AWS admet (que són moltes: PostGIS, pg_stat_statements, pgvector…).
- Les versions tenen calendari de fi de suport i AWS acabarà actualitzant-te.
RDS davant de PostgreSQL instal·lat en una EC2
La pregunta legítima del Luis és: «podríem instal·lar PostgreSQL en una EC2 i surt més barat, oi?». La resposta honesta és que el preu per hora és menor, i el cost total gairebé mai.
| Criteri | PostgreSQL en EC2 | Amazon RDS |
|---|---|---|
| Cost per hora | Menor (només la instància + EBS) | ~25-40 % més car pel servei gestionat |
| Temps de posada en marxa | Hores o dies | 10 minuts |
| Alta disponibilitat | Muntar Patroni/repmgr a mà | Casella Multi-AZ |
| Còpies | Scripts propis que cal mantenir | Automàtiques, amb PITR al segon |
| Pedaços | El teu calendari, la teva responsabilitat | Finestra de manteniment |
| Accés al SO | Sí, control total | No |
| Extensions exòtiques | Qualsevol | Només les admeses |
| Versions molt antigues o molt noves | Qualsevol | Les que ofereixi AWS |
| Cost de personal | Alt i continu | Baix |
Tria EC2 només si necessites control del sistema operatiu, una extensió no admesa, una versió concreta fora del catàleg, o si tens un equip d'administradors de bases de dades que ja fa aquesta feina. Per a MercadoFresco, que té la Marta a mitja jornada per a tot, RDS no és una opció: és l'única opció sensata.
El càlcul que tanca la discussió: una db.t3.small a eu-west-1 costa al voltant de 30 USD al
mes davant d'uns 20 USD de l'EC2 equivalent. Deu dòlars de diferència. Una sola incidència
nocturna de PostgreSQL a l'any, amb la Marta desperta a les 3:00, costa més que això.
Motors disponibles i quin tria MercadoFresco
| Motor | Quan es tria |
|---|---|
| PostgreSQL | Estàndard obert, molt complet, extensions (PostGIS, pgvector). Elecció de MercadoFresco |
| MySQL | Enorme base instal·lada, aplicacions PHP heretades |
| MariaDB | Bifurcació de MySQL amb llicència plenament lliure |
| Oracle | Migracions de sistemes empresarials existents; llicència cara |
| SQL Server | Ecosistema Microsoft; llicència inclosa o pròpia |
| Db2 | Sistemes heretats d'IBM |
| Aurora (compatible amb PostgreSQL/MySQL) | Motor propi d'AWS, fins a 5× MySQL i 3× PostgreSQL, emmagatzematge distribuït en 3 AZ. Es veu a la lliçó 06-03 |
MercadoFresco ja feia servir PostgreSQL al servidor de l'oficina, així que RDS PostgreSQL permet migrar sense reescriure consultes. És la decisió de menor risc.
Un aclariment que estalvia confusió: Aurora també és RDS, es gestiona des de la mateixa consola i comparteix gairebé tota l'operativa que veurem aquí, però la seva arquitectura d'emmagatzematge és diferent. A 06-03 valorarem si a MercadoFresco li compensa migrar a Aurora quan obri a tres ciutats més. I l'elecció general entre relacional, clau-valor o magatzem de columnes és la lliçó 06-01.
Crear la instància RDS per consola
- Consola → RDS → verifica la regió Irlanda (
eu-west-1) → Crear base de dades. - Mètode: Creació estàndard (la fàcil amaga opcions que necessites veure).
- Motor: PostgreSQL, versió 16.x.
- Plantilla: Producció activa Multi-AZ i l'emmagatzematge provisionat per defecte. Per aprendre, tria Capa gratuïta i així no gastes; aquí descrivim la de producció.
- Configuració:
- Identificador:
mercadofresco-pedidos - Usuari mestre:
mfadmin(no facis servirpostgresniadmin) - Contrasenya: marca Gestionar credencials mestres a AWS Secrets Manager. Amb això la contrasenya no la veus mai, no l'escrius mai i AWS la rota sola. Secrets Manager és la lliçó 04-03.
- Identificador:
- Configuració de la instància:
db.t3.small(2 vCPU, 2 GiB). Per a producció real de MercadoFresco,db.m6g.large. - Emmagatzematge: gp3, 20 GiB, amb escalat automàtic activat i màxim 100 GiB.
- Disponibilitat: Instància en espera Multi-AZ. És la casella que resol la meitat del problema 1 per a la base de dades.
- Connectivitat: VPC per defecte, accés públic = No, grup de seguretat
sg-mercadofresco-basedatos. La xarxa es veu al mòdul 3 (03-01 VPC, 03-02 grups de seguretat). - Autenticació: contrasenya; opcionalment autenticació IAM, que elimina les contrasenyes.
- Configuració addicional:
- Nom de base de dades inicial:
pedidos - Còpies automàtiques: 7 dies de retenció
- Finestra de còpies: 02:00-03:00 UTC (matinada a Espanya, trànsit mínim)
- Finestra de manteniment: diumenge 04:00-05:00 UTC
- Xifratge activat
- Protecció contra eliminació: activada
- Performance Insights: activat (7 dies són gratuïts)
- Nom de base de dades inicial:
- Revisa l'estimació de cost mensual que mostra la consola i prem Crear base de dades.
La creació triga entre 5 i 15 minuts (més amb Multi-AZ, perquè construeix dues instàncies).
Avís de cost. Una
db.t3.microd'una sola AZ entra a la capa gratuïta durant 12 mesos (750 h/mes, 20 GB d'emmagatzematge i 20 GB de còpies). Multi-AZ duplica el cost de còmput i no és a la capa gratuïta. Si estàs practicant, crea la instància sense Multi-AZ i activa la casella només una estona per veure com funciona. L'apartat final explica com aturar-la i esborrar-la.
Crear la instància RDS per CLI
# 1. Grup de subxarxes: indica a RDS en quines subxarxes pot col·locar la instància.
# N'hi ha d'haver almenys DUES, en DUES AZ diferents: és el requisit de Multi-AZ.
aws rds create-db-subnet-group \
--db-subnet-group-name sng-mercadofresco \
--db-subnet-group-description "Subxarxes privades de MercadoFresco en dues AZ" \
--subnet-ids subnet-aaa11111 subnet-bbb22222 \
--tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=produccion \
Key=Componente,Value=pedidos Key=Propietario,Value=marta \
Key=CentroCoste,Value=operaciones \
--profile mercadofresco-dev --region eu-west-1
# 2. La instància
aws rds create-db-instance \
--db-instance-identifier mercadofresco-pedidos \
--db-instance-class db.t3.small \
--engine postgres \
--engine-version 16.3 \
--master-username mfadmin \
--manage-master-user-password \
--allocated-storage 20 \
--max-allocated-storage 100 \
--storage-type gp3 \
--storage-encrypted \
--db-subnet-group-name sng-mercadofresco \
--vpc-security-group-ids sg-0abc123def456 \
--no-publicly-accessible \
--multi-az \
--backup-retention-period 7 \
--preferred-backup-window "02:00-03:00" \
--preferred-maintenance-window "sun:04:00-sun:05:00" \
--enable-performance-insights \
--performance-insights-retention-period 7 \
--deletion-protection \
--db-name pedidos \
--tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=produccion \
Key=Componente,Value=pedidos Key=Propietario,Value=marta \
Key=CentroCoste,Value=operaciones \
--profile mercadofresco-dev --region eu-west-1
# 3. Esperar que estigui disponible (bloqueja fins que acabi)
aws rds wait db-instance-available \
--db-instance-identifier mercadofresco-pedidos \
--profile mercadofresco-dev --region eu-west-1
# 4. Obtenir el punt d'enllaç (endpoint) al qual es connectarà l'aplicació
aws rds describe-db-instances \
--db-instance-identifier mercadofresco-pedidos \
--query 'DBInstances[0].{Endpoint:Endpoint.Address,Port:Endpoint.Port,
Estat:DBInstanceStatus,MultiAZ:MultiAZ,AZ:AvailabilityZone}' \
--output table \
--profile mercadofresco-dev --region eu-west-1Els paràmetres que més importen:
--manage-master-user-password: AWS genera la contrasenya, la desa a Secrets Manager i la rota automàticament. No l'escrius ni la veus mai. És la millor pràctica actual i evita el clàssic--master-user-password "Password123"a l'historial de l'intèrpret d'ordres.--no-publicly-accessible: la base de dades no té IP pública. Només s'hi accedeix des de dins de la VPC. Innegociable per a dades de clients.--max-allocated-storage 100: activa l'escalat automàtic d'emmagatzematge. Si el disc arriba al 90 % d'ocupació, RDS l'amplia sol fins a aquest sostre.--deletion-protection: impedeix esborrar la instància per error. Per esborrar-la de debò cal desactivar-lo primer, en un pas conscient i separat.
El punt d'enllaç tindrà aquesta forma:
És un nom DNS, no una IP, i això és fonamental. Quan es produeixi una commutació per error, AWS canviarà a què apunta aquest nom i l'aplicació es reconnectarà al servidor nou sense canviar ni una línia de configuració. Si en algun lloc del codi de MercadoFresco hi ha una IP de base de dades escrita a mà, cal treure-la ara.
Multi-AZ: què és realment una rèplica síncrona en espera
Aquí hi ha un malentès molt estès que convé desfer amb claredat: la instància en espera de Multi-AZ no serveix trànsit. No és un segon servidor que reparteix càrrega. No t'hi pots connectar. És una còpia sincronitzada esperant que la principal falli.
flowchart TB
APP["Aplicacio de MercadoFresco<br/>instancies EC2 de la botiga"]
EP["Punt d'enllac DNS<br/>mercadofresco-pedidos...rds.amazonaws.com"]
APP --> EP
EP --> P
subgraph AZ1["eu-west-1a"]
P["PRINCIPAL<br/>lectures i escriptures"]
end
subgraph AZ2["eu-west-1b"]
S["EN ESPERA<br/>sense transit<br/>no accessible"]
end
P -->|"replicacio SINCRONA<br/>cada commit es confirma<br/>a totes dues abans de respondre"| S
P -.->|"copies automatiques<br/>es prenen de la instancia en espera:<br/>sense impacte en produccio"| B["Copies a S3"]
Com funciona la replicació síncrona: quan l'aplicació confirma una transacció, PostgreSQL escriu a la principal i espera que l'escriptura s'hagi confirmat també a la instància en espera abans de respondre «fet» al client. Conseqüència doble:
- Avantatge: zero pèrdua de dades (RPO = 0). El que està confirmat és a les dues AZ.
- Cost: cada escriptura triga una mica més, perquè inclou un viatge de xarxa entre AZ (típicament 1-2 ms). En càrregues amb escriptures molt intenses es nota.
Què passa exactament en una commutació per error
- AWS detecta la fallada (de la instància, de l'emmagatzematge o de l'AZ sencera).
- Canvia el registre DNS del punt d'enllaç perquè apunti a la instància en espera.
- L'antiga instància en espera passa a ser la principal.
- AWS crea una nova instància en espera a l'altra AZ, en segon pla.
Durada típica: 60-120 segons. Durant aquesta estona l'aplicació rep errors de connexió. Multi-AZ no és màgia invisible: és recuperació ràpida, no absència d'interrupció. L'aplicació ha d'estar preparada:
- Reintents amb espera exponencial a les operacions de base de dades.
- TTL de DNS baix al resolutor del client. Un conjunt de connexions que desa la IP a la memòria cau per sempre continuarà intentant connectar-se al servidor caigut.
- Conjunt de connexions que sàpiga descartar connexions mortes (
pool_pre_pinga SQLAlchemy).
Es pot provocar una commutació a propòsit per comprovar que l'aplicació aguanta. Fes-ho en un entorn de proves, i fes-ho abans que passi sense avisar:
aws rds reboot-db-instance \
--db-instance-identifier mercadofresco-pedidos-pruebas \
--force-failover \
--profile mercadofresco-dev --region eu-west-1Multi-AZ davant de rèplica de lectura
Són coses diferents i es confonen constantment:
| Multi-AZ (instància en espera) | Rèplica de lectura | |
|---|---|---|
| Per a què serveix | Alta disponibilitat | Escalar les lectures |
| Replicació | Síncrona | Asíncrona (hi ha retard) |
| Se'n pot llegir? | No | Sí |
| S'hi pot escriure? | No | No (llevat que la promoguis) |
| Commutació automàtica | Sí | No (promoció manual) |
| Ubicació | Una altra AZ de la mateixa regió | Mateixa AZ, una altra AZ o una altra regió |
| Nombre | 1 (o 2 amb el mode clúster Multi-AZ) | Fins a 15 a PostgreSQL |
| Impacte en la latència d'escriptura | Sí, l'augmenta | No |
| Cost | Duplica el còmput | Una instància addicional per rèplica |
MercadoFresco necessita totes dues, i per raons diferents: Multi-AZ perquè el negoci no pot perdre comandes, i rèpliques de lectura perquè els informes de la Sara estan matant la base de dades.
Rèpliques de lectura: els informes de la Sara sense castigar producció
El problema real, mesurat: la Sara executa cada dilluns al matí una consulta que agrega les comandes del mes per barri i per franja horària. Triga 4 minuts i durant aquesta estona la botiga va lenta, perquè el mateix servidor està atenent els clients.
Una rèplica de lectura és una còpia asíncrona de la base de dades que accepta consultes de només lectura. Les escriptures continuen anant a la principal; les lectures pesades es dirigeixen a la rèplica.
aws rds create-db-instance-read-replica \
--db-instance-identifier mercadofresco-pedidos-lectura \
--source-db-instance-identifier mercadofresco-pedidos \
--db-instance-class db.t3.small \
--availability-zone eu-west-1b \
--tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=produccion \
Key=Componente,Value=analitica Key=Propietario,Value=sara \
Key=CentroCoste,Value=marketing \
--profile mercadofresco-dev --region eu-west-1Fixa't en l'etiquetatge: Componente=analitica, Propietario=sara, CentroCoste=marketing. La
rèplica existeix per a la Sara, així que el seu cost s'imputa a màrqueting i no a operacions. Això és
exactament el que farà possible l'informe d'assignació de costos de la lliçó 11-02.
Punts que cal tenir clars:
- La replicació és asíncrona: la rèplica va uns segons per darrere. Vigila la mètrica
ReplicaLag. Per a informes agregats de vendes és perfectament acceptable; per a «consultar l'estat de la comanda que acabo de fer», no. - L'aplicació ha de dirigir el trànsit. AWS et dona un punt d'enllaç diferent per a la rèplica; el codi decideix quin fa servir. RDS no reparteix sol.
- Una rèplica es pot promoure a instància independent, cosa que trenca la replicació de manera irreversible. És una estratègia vàlida de migració entre regions.
- Es poden crear en una altra regió, cosa que a més dona recuperació davant de desastres geogràfica.
Al codi de MercadoFresco, la separació queda així:
import os
import psycopg
# Dues cadenes de connexió diferents, dos usos diferents.
DSN_ESCRIPTURA = os.environ["MF_DB_ESCRITURA"] # apunta a mercadofresco-pedidos
DSN_LECTURA = os.environ["MF_DB_LECTURA"] # apunta a mercadofresco-pedidos-lectura
def crear_comanda(client_id: int, linies: list) -> int:
"""Escriptura: SEMPRE contra la instància principal."""
with psycopg.connect(DSN_ESCRIPTURA) as con, con.cursor() as cur:
cur.execute(
"INSERT INTO pedidos (cliente_id, creado_en) VALUES (%s, now()) RETURNING id",
(client_id,),
)
comanda_id = cur.fetchone()[0]
cur.executemany(
"INSERT INTO lineas_pedido (pedido_id, producto_id, cantidad) VALUES (%s,%s,%s)",
[(comanda_id, li["producto_id"], li["cantidad"]) for li in linies],
)
con.commit()
return comanda_id
def informe_vendes_per_barri(mes: str) -> list:
"""Lectura analitica pesada: contra la REPLICA, per no afectar la botiga."""
with psycopg.connect(DSN_LECTURA) as con, con.cursor() as cur:
cur.execute(
"""
SELECT c.barrio,
date_trunc('hour', p.creado_en) AS franja,
count(*) AS num_comandes,
sum(lp.cantidad) AS unitats
FROM pedidos p
JOIN clientes c ON c.id = p.cliente_id
JOIN lineas_pedido lp ON lp.pedido_id = p.id
WHERE to_char(p.creado_en, 'YYYY-MM') = %s
GROUP BY c.barrio, franja
ORDER BY num_comandes DESC
""",
(mes,),
)
return cur.fetchall()La consulta en SQL pur, per veure-la completa i entendre per què és cara: recorre totes les comandes del mes, les uneix amb clients i línies de comanda, i agrega per dues dimensions. Amb centenars de milers de files això és un recorregut seqüencial llarg que satura la CPU i expulsa dades calentes de la memòria cau de PostgreSQL. Justament el que no vols que passi mentre 900 clients estan comprant.
Còpies automàtiques, retenció i restauració a un punt en el temps
Aquí es tanca el problema 2 de MercadoFresco.
RDS fa dues coses de manera contínua i automàtica:
- Una còpia completa diària durant la finestra que hagis fixat (02:00-03:00 UTC en el nostre cas). Amb Multi-AZ, es pren de la instància en espera, així que producció no ho nota.
- Còpia contínua dels registres de transaccions (WAL) a S3, cada 5 minuts.
La combinació de totes dues és el que permet la restauració a un punt en el temps (Point-In-Time Recovery, PITR): pots restaurar la base de dades a qualsevol segon dins del període de retenció, no només a l'hora de la còpia diària.
L'escenari que justifica tot això: el dimarts a les 11:47, un desplegament del Luis executa per error
un UPDATE sense WHERE que posa a zero el preu de tots els productes. A les 11:52 algú se
n'adona.
# Veure fins a quin moment es pot restaurar
aws rds describe-db-instances \
--db-instance-identifier mercadofresco-pedidos \
--query 'DBInstances[0].LatestRestorableTime' \
--profile mercadofresco-dev --region eu-west-1
# Restaurar a les 11:46, un minut abans del desastre.
# IMPORTANT: crea una instància NOVA. L'original no es toca.
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier mercadofresco-pedidos \
--target-db-instance-identifier mercadofresco-pedidos-recuperada \
--restore-time 2026-08-04T11:46:00Z \
--db-subnet-group-name sng-mercadofresco \
--vpc-security-group-ids sg-0abc123def456 \
--no-publicly-accessible \
--tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=pruebas \
Key=Componente,Value=pedidos Key=Propietario,Value=marta \
Key=CentroCoste,Value=operaciones \
--profile mercadofresco-dev --region eu-west-1Que la restauració creï una instància nova és deliberat i molt útil: pots verificar les dades abans de tocar producció, o fins i tot extreure només la taula afectada i copiar-la, en comptes de tirar enrere tota la base de dades i perdre les comandes legítimes d'aquests cinc minuts.
Sobre la retenció:
| Retenció | Efecte |
|---|---|
| 0 dies | Desactiva les còpies automàtiques i el PITR. Mai en producció |
| 1-7 dies | Valor per defecte (7). Suficient per a errors que es detecten ràpid |
| 8-35 dies | Màxim. Per a requisits de compliment o errors de detecció lenta |
Les còpies automàtiques s'emmagatzemen de franc fins a la mida de la base de dades; més enllà es cobren a preu d'instantània. I hi ha un detall crític: en eliminar la instància, les còpies automàtiques s'esborren amb ella. Només les instantànies manuals sobreviuen.
Instantànies manuals i el tancament del problema 2
Una instantània manual és una còpia que crees tu i que viu fins que tu l'esborres, fins i tot si elimines la instància. És la còpia per a fites: abans d'una migració d'esquema, abans d'una actualització de versió major, al tancament de l'exercici fiscal.
# Abans d'aplicar la migració d'esquema de la campanya de Nadal
aws rds create-db-snapshot \
--db-instance-identifier mercadofresco-pedidos \
--db-snapshot-identifier mf-pedidos-antes-migracion-navidad-2026 \
--tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=produccion \
Key=Componente,Value=pedidos Key=Propietario,Value=marta \
Key=CentroCoste,Value=operaciones \
--profile mercadofresco-dev --region eu-west-1
# Copiar la instantània a una altra regió per a recuperació davant de desastres
aws rds copy-db-snapshot \
--source-db-snapshot-identifier \
arn:aws:rds:eu-west-1:111122223333:snapshot:mf-pedidos-antes-migracion-navidad-2026 \
--target-db-snapshot-identifier mf-pedidos-dr-navidad-2026 \
--kms-key-id alias/aws/rds \
--profile mercadofresco-dev --region eu-central-1Comparació de les tres formes de recuperació a RDS:
| Còpies automàtiques (PITR) | Instantània manual | AWS Backup | |
|---|---|---|---|
| Qui les crea | RDS, cada dia | Tu | Pla centralitzat |
| Granularitat | Qualsevol segon | L'instant de la creació | Segons el pla |
| Retenció | 0-35 dies | Indefinida | La que defineixis |
| Sobreviuen a l'esborrament de la instància | No | Sí | Sí |
| Còpia entre regions | No directament | Sí | Sí |
| Ús típic | Errors humans recents | Fites, retenció llarga | Govern unificat de tots els serveis |
I així queda tancat el problema 2 de MercadoFresco, sumant el de 02-02 i el d'aquesta lliçó:
| Abans (servidor de l'oficina) | Ara (AWS) | |
|---|---|---|
| Còpia de les fotos | Disc extern manual | Instantànies EBS automàtiques amb DLM + S3 amb versionatge |
| Còpia de la base de dades | pg_dump quan algú se'n recordava |
Automàtica diària + WAL cada 5 min |
| Restaurar a un moment concret | Impossible | PITR a qualsevol segon dels últims 7 dies |
| Còpia fora de l'edifici | No | Instantànies replicades a eu-central-1 |
| Temps de restauració | Hores, si l'abocament servia | 10-20 minuts |
| Prova de restauració | No es va fer mai | Trimestral, en instància a part, sense tocar producció |
Amb un advertiment que es repeteix i no sobra: la prova de restauració trimestral és part del pla, no un extra. La Marta la té al calendari.
Grups de paràmetres i finestres de manteniment
Com que no hi ha accés al sistema operatiu, no pots editar postgresql.conf. En comptes d'això, RDS fa servir
grups de paràmetres: un conjunt amb nom d'ajustos que s'associa a una o diverses instàncies.
El grup per defecte no es pot modificar, així que el primer és crear-ne un de propi:
aws rds create-db-parameter-group \
--db-parameter-group-name pg16-mercadofresco \
--db-parameter-group-family postgres16 \
--description "Parametres de PostgreSQL 16 per a MercadoFresco" \
--profile mercadofresco-dev --region eu-west-1
aws rds modify-db-parameter-group \
--db-parameter-group-name pg16-mercadofresco \
--parameters \
"ParameterName=log_min_duration_statement,ParameterValue=1000,ApplyMethod=immediate" \
"ParameterName=shared_preload_libraries,ParameterValue=pg_stat_statements,ApplyMethod=pending-reboot" \
"ParameterName=log_connections,ParameterValue=1,ApplyMethod=immediate" \
--profile mercadofresco-dev --region eu-west-1
aws rds modify-db-instance \
--db-instance-identifier mercadofresco-pedidos \
--db-parameter-group-name pg16-mercadofresco \
--apply-immediately \
--profile mercadofresco-dev --region eu-west-1Què hem configurat i per què:
log_min_duration_statement = 1000: registra tota consulta que trigui més d'1 segon. És la manera més directa de trobar les consultes que enfonsen la botiga els divendres.shared_preload_libraries = pg_stat_statements: activa l'extensió que acumula estadístiques per consulta. Base de qualsevol treball seriós d'optimització.ApplyMethod:immediates'aplica a l'instant;pending-rebootrequereix reiniciar la instància. Un paràmetre dinàmic marcat com a pendent no està fent res encara, i això despista molt.
Sobre la finestra de manteniment: és l'interval setmanal en què AWS aplica pedaços del sistema operatiu i del motor. Tria-la a la vall de trànsit (diumenge de matinada per a MercadoFresco, mai un divendres a la tarda). Amb Multi-AZ, el manteniment s'aplica primer a la instància en espera, després es commuta i després s'apedaça l'altra: la interrupció es redueix al temps de la commutació.
Les actualitzacions de versió menor poden ser automàtiques (--auto-minor-version-upgrade);
les de versió major (de PostgreSQL 16 a 17) no ho són mai: requereixen la teva acció explícita i cal
provar-les abans en una instància restaurada des d'una instantània.
Monitoratge: mètriques bàsiques i Performance Insights
RDS publica mètriques a CloudWatch sense configurar res. Les que cal mirar:
| Mètrica | Què indica | Llindar d'alarma suggerit |
|---|---|---|
CPUUtilization |
Ús de CPU | > 80 % durant 10 min |
DatabaseConnections |
Connexions obertes | > 80 % de max_connections |
FreeableMemory |
Memòria disponible | < 10 % de la RAM total |
FreeStorageSpace |
Espai lliure al disc | < 10 % (o < 5 GB) |
ReadLatency / WriteLatency |
Latència de disc | > 20 ms sostingut |
ReplicaLag |
Retard de la rèplica de lectura | > 30 s |
DiskQueueDepth |
Operacions de disc a la cua | > 5 sostingut |
Performance Insights va un pas més enllà: és un tauler que mostra la càrrega de la base de
dades descomposta per consulta, per usuari, per amfitrió i per tipus d'espera. Aquesta última
dimensió és la que resol incidències: no et diu només «la CPU està al 90 %», et diu «el 70 % de
la càrrega està esperant bloqueigs de la taula pedidos, i la consulta responsable és aquesta».
Els 7 dies de retenció són gratuïts i val la pena activar-ho sempre. El monitoratge a fons, amb alarmes, taulers i agregació de registres, és la lliçó 05-01.
# Alarma sobre l'espai lliure: la fallada més previsible i més evitable
aws cloudwatch put-metric-alarm \
--alarm-name mercadofresco-pedidos-espacio-bajo \
--alarm-description "Menys de 5 GB lliures a la base de dades de comandes" \
--namespace AWS/RDS --metric-name FreeStorageSpace \
--dimensions Name=DBInstanceIdentifier,Value=mercadofresco-pedidos \
--statistic Average --period 300 --evaluation-periods 2 \
--threshold 5000000000 --comparison-operator LessThanThreshold \
--alarm-actions arn:aws:sns:eu-west-1:111122223333:alertas-mercadofresco \
--profile mercadofresco-dev --region eu-west-1Connectar-se des de l'aplicació sense credencials al codi
Primer, la comprovació manual des d'una instància EC2 de la botiga (recorda: la base de dades no és pública, així que cal connectar-s'hi des de dins de la VPC):
# Recuperar la contrasenya generada per AWS des de Secrets Manager.
# No es copia mai a un fitxer ni s'escriu a l'historial.
export PGPASSWORD=$(aws secretsmanager get-secret-value \
--secret-id "rds!db-a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
--query 'SecretString' --output text \
--profile mercadofresco-dev --region eu-west-1 | python3 -c "import sys,json; print(json.load(sys.stdin)['password'])")
psql -h mercadofresco-pedidos.abc123xyz.eu-west-1.rds.amazonaws.com \
-U mfadmin -d pedidos -p 5432
unset PGPASSWORDUn cop a dins, comprovacions útils:
-- Versió del motor
SELECT version();
-- Mida de la base de dades
SELECT pg_size_pretty(pg_database_size('pedidos')) AS mida;
-- Les 5 consultes més lentes (requereix pg_stat_statements activat)
SELECT substring(query, 1, 80) AS consulta,
calls,
round(mean_exec_time::numeric, 2) AS ms_mitjans,
round(total_exec_time::numeric, 2) AS ms_totals
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 5;
-- Connexions actives per estat
SELECT state, count(*) FROM pg_stat_activity GROUP BY state;I així es connecta l'aplicació, llegint el secret a l'arrencada i sense que cap credencial toqui el codi ni el repositori:
"""
Connexió de la botiga de MercadoFresco a RDS PostgreSQL.
Les credencials es llegeixen de Secrets Manager fent servir el rol IAM de la instància EC2:
no hi ha contrasenyes al codi, ni a variables d'entorn, ni al repositori.
"""
import json
import os
import boto3
import psycopg
from psycopg_pool import ConnectionPool
REGION = "eu-west-1"
ID_SECRET = os.environ["MF_SECRETO_BD"] # només l'identificador, no la clau
HOST_ESCRIPTURA = os.environ["MF_BD_HOST_ESCRITURA"]
HOST_LECTURA = os.environ["MF_BD_HOST_LECTURA"]
def _credencials() -> dict:
"""Llegeix usuari i contrasenya de Secrets Manager.
El rol IAM de la instància EC2 (o de la Lambda) autoritza aquesta crida:
no cal cap clau d'accés. Detall a les lliçons 04-01 i 04-03.
"""
client = boto3.client("secretsmanager", region_name=REGION)
resposta = client.get_secret_value(SecretId=ID_SECRET)
return json.loads(resposta["SecretString"])
def _dsn(host: str) -> str:
c = _credencials()
# sslmode=require obliga a xifrar la connexió en trànsit.
return (
f"host={host} port=5432 dbname=pedidos "
f"user={c['username']} password={c['password']} "
f"sslmode=require connect_timeout=5"
)
# Conjunts de connexions separats. min_size manté connexions obertes per evitar el cost
# d'establir-les a cada petició durant el pic dels divendres.
pool_escriptura = ConnectionPool(_dsn(HOST_ESCRIPTURA), min_size=2, max_size=10)
pool_lectura = ConnectionPool(_dsn(HOST_LECTURA), min_size=1, max_size=5)
def estat_comanda(comanda_id: int) -> dict | None:
"""Consulta de només lectura que SÍ ha d'anar a la principal.
El client acaba de fer la comanda: el retard de la rèplica podria
fer que no la trobés. Regla: el que l'usuari acaba d'escriure,
es llegeix de la principal.
"""
with pool_escriptura.connection() as con, con.cursor() as cur:
cur.execute(
"SELECT id, estado, creado_en, entrega_estimada FROM pedidos WHERE id = %s",
(comanda_id,),
)
fila = cur.fetchone()
if fila is None:
return None
return {
"id": fila[0],
"estado": fila[1],
"creado_en": fila[2].isoformat(),
"entrega_estimada": fila[3].isoformat() if fila[3] else None,
}Les tres regles que resumeix aquest codi:
- Cap credencial al codi ni al repositori. Només l'identificador del secret.
- Autorització per rol IAM, no per claus d'accés. La instància EC2 té un rol que li permet llegir aquest secret concret i res més.
sslmode=require: la connexió va xifrada. RDS proporciona el certificat.
Escalat vertical i emmagatzematge autoescalable
Escalat vertical (canviar la classe d'instància). És una operació amb interrupció, llevat que hi hagi Multi-AZ, on AWS modifica primer la instància en espera, commuta i després l'altra: l'aturada es redueix als 60-120 segons de la commutació.
aws rds modify-db-instance \
--db-instance-identifier mercadofresco-pedidos \
--db-instance-class db.m6g.large \
--apply-immediately \
--profile mercadofresco-dev --region eu-west-1--apply-immediately aplica el canvi ja, amb la interrupció corresponent. Sense aquest
paràmetre, el canvi espera a la finestra de manteniment, que és el que vols en producció llevat
d'urgència.
Escalat de l'emmagatzematge. Es pot ampliar en qualsevol moment i sense aturar res, però no
reduir. Amb --max-allocated-storage, RDS ho fa sol:
aws rds modify-db-instance \
--db-instance-identifier mercadofresco-pedidos \
--allocated-storage 50 --max-allocated-storage 200 \
--apply-immediately \
--profile mercadofresco-dev --region eu-west-1Quan escalar cada cosa, en el cas de MercadoFresco:
| Símptoma | Causa probable | Acció |
|---|---|---|
| CPU al 90 % amb consultes lentes | Falta CPU o falten índexs | Primer mira els índexs; després puja de classe |
FreeableMemory baix, molta lectura de disc |
El conjunt de treball no cap a la RAM | Classe amb més memòria (família R) |
| Moltes lectures analítiques | Informes de la Sara | Rèplica de lectura, no una instància més gran |
FreeStorageSpace baixant |
Creixement normal | Escalat automàtic d'emmagatzematge |
| Latència d'escriptura alta | IOPS insuficients | Pujar IOPS de gp3 o passar a io2 |
L'ordre importa: pujar de mida és l'última opció, no la primera. Un índex que falta costa zero euros al mes; una classe d'instància més gran costa tots els mesos, per sempre.
Migrar des del servidor de l'oficina
Amb la base de dades de MercadoFresco (uns pocs GB i una finestra de manteniment nocturna acceptable), la migració clàssica amb abocament i restauració és suficient.
# ---------- Al servidor de l'oficina ----------
# 1. Abocament en format "custom": comprimit i restaurable en paral·lel.
pg_dump -h localhost -U postgres -d pedidos \
--format=custom --compress=9 --verbose \
--file=pedidos-2026-08-04.dump
# 2. Comprovar l'abocament abans de confiar-hi
pg_restore --list pedidos-2026-08-04.dump | head -20
ls -lh pedidos-2026-08-04.dump
# ---------- Des d'una EC2 dins de la VPC ----------
# 3. Pujar l'abocament a S3 (bucket privat, xifrat amb KMS)
aws s3 cp pedidos-2026-08-04.dump \
s3://mercadofresco-copias-basedatos/copias/base-datos/ \
--profile mercadofresco-dev
# 4. Descarregar-lo a l'EC2 i restaurar contra RDS.
# -j 4 restaura amb 4 processos en paral·lel: molt més ràpid.
pg_restore -h mercadofresco-pedidos.abc123xyz.eu-west-1.rds.amazonaws.com \
-U mfadmin -d pedidos \
--no-owner --no-privileges --verbose -j 4 \
pedidos-2026-08-04.dumpPer què --no-owner --no-privileges: els rols i permisos del servidor d'origen no existeixen a RDS,
i sense aquestes opcions la restauració s'omple d'errors per intentar assignar objectes a usuaris
inexistents.
Verificació obligatòria abans de commutar el trànsit:
-- Comparar el nombre de files de les taules principals amb l'origen
SELECT 'pedidos' AS tabla, count(*) FROM pedidos
UNION ALL SELECT 'clientes', count(*) FROM clientes
UNION ALL SELECT 'productos', count(*) FROM productos
UNION ALL SELECT 'lineas_pedido', count(*) FROM lineas_pedido;
-- Comprovar que els índexs i les restriccions han arribat
SELECT tablename, indexname FROM pg_indexes
WHERE schemaname = 'public' ORDER BY tablename;
-- Actualitzar les estadístiques del planificador: sense això, les consultes
-- poden anar absurdament lentes just després de restaurar.
ANALYZE VERBOSE;Pla de commutació de MercadoFresco, un diumenge de matinada:
- 02:00 — Posar la botiga en mode manteniment (només lectura).
- 02:05 —
pg_dumpfinal del servidor de l'oficina. - 02:20 —
pg_restorea RDS iANALYZE. - 02:40 — Verificar recomptes i executar la bateria de proves de fum.
- 02:50 — Canviar les variables d'entorn de l'aplicació al nou punt d'enllaç.
- 03:00 — Treure el mode manteniment i vigilar mètriques durant una hora.
- El servidor de l'oficina es deixa encès i sincronitzat una setmana, per si cal tirar enrere.
Quan no es pot aturar la botiga, l'eina és AWS DMS (Database Migration Service): copia l'estat inicial i després replica els canvis en continu (change data capture), de manera que la finestra de tall es redueix a segons. A més pot migrar entre motors diferents (d'Oracle a PostgreSQL, per exemple). Per a MercadoFresco és exagerat; per a una migració sense aturada, és el camí.
Costos i com aturar una instància de proves
Components de la factura de RDS:
| Component | Preu orientatiu (eu-west-1) |
|---|---|
| Hores d'instància | db.t3.micro ≈ 0,018 USD/h · db.t3.small ≈ 0,036 · db.m6g.large ≈ 0,171 |
| Multi-AZ | ×2 sobre les hores d'instància |
| Emmagatzematge gp3 | ≈ 0,127 USD/GB-mes |
| Còpies | Gratis fins a la mida de la base de dades; després ≈ 0,105 USD/GB-mes |
| Rèplica de lectura | Com una instància més |
| Transferència entre AZ | Gratis dins de Multi-AZ; de pagament cap a internet |
| Performance Insights | 7 dies gratis; més retenció, de pagament |
Cost mensual de la configuració de producció de MercadoFresco:
Instancia db.t3.small Multi-AZ: 0,036 × 2 × 730 = 52,56 USD Emmagatzematge 50 GB × 0,127 = 6,35 USD Còpies (50 GB, dins del que és gratuït) = 0,00 USD Rèplica de lectura db.t3.small = 26,28 USD -------------------------------------------------------------- Total ≈ 85,19 USD/mes
Uns 78 € al mes per una base de dades amb alta disponibilitat, còpies automàtiques, PITR de 7 dies i una rèplica per a analítica. Comparat amb els 6.000 € del servidor original —que no tenia res d'això— i amb el temps que la Marta dedicava a mantenir-lo, la conversa econòmica es torna fàcil.
Aturar una instància de proves:
# S'atura el còmput (deixa de facturar-se); l'emmagatzematge continua costant.
aws rds stop-db-instance \
--db-instance-identifier mercadofresco-pedidos-pruebas \
--profile mercadofresco-dev --region eu-west-1
aws rds start-db-instance \
--db-instance-identifier mercadofresco-pedidos-pruebas \
--profile mercadofresco-dev --region eu-west-1Dues limitacions importants: RDS només permet tenir una instància aturada 7 dies; al vuitè l'arrenca sola. I una instància Multi-AZ no es pot aturar. Per a entorns de desenvolupament que només es fan servir en horari laboral, el pràctic és programar l'arrencada i l'aturada, o simplement esborrar i recrear des d'una instantània.
Eliminar per complet quan acabis la pràctica:
# 1. Treure la protecció contra eliminació (pas conscient i separat)
aws rds modify-db-instance \
--db-instance-identifier mercadofresco-pedidos-pruebas \
--no-deletion-protection --apply-immediately \
--profile mercadofresco-dev --region eu-west-1
# 2. Eliminar les rèpliques primer
aws rds delete-db-instance \
--db-instance-identifier mercadofresco-pedidos-lectura \
--skip-final-snapshot \
--profile mercadofresco-dev --region eu-west-1
# 3. Eliminar la principal, guardant una instantània final per si de cas
aws rds delete-db-instance \
--db-instance-identifier mercadofresco-pedidos-pruebas \
--final-db-snapshot-identifier mf-pedidos-final-$(date +%Y%m%d) \
--profile mercadofresco-dev --region eu-west-1
# 4. Les instantànies manuals continuen costant. Revisa-les i esborra-les si no les necessites.
aws rds describe-db-snapshots --snapshot-type manual \
--query 'DBSnapshots[].{ID:DBSnapshotIdentifier,GB:AllocatedStorage,Data:SnapshotCreateTime}' \
--output table \
--profile mercadofresco-dev --region eu-west-1Errors Habituals i Consells
- Creure que la instància en espera de Multi-AZ serveix lectures. No. Per a això hi ha les rèpliques de lectura. És el malentès número u de RDS.
- Posar
--publicly-accessibleper «poder connectar-me des de casa». Exposa la base de dades a internet. La manera correcta és un bastió, Session Manager o una VPN. - Escriure la contrasenya a la comanda o al codi. Fes servir
--manage-master-user-passwordi Secrets Manager (04-03). - Retenció de còpies a 0 dies. Desactiva el PITR. És la configuració que converteix un error humà recuperable en una pèrdua definitiva.
- Oblidar que les còpies automàtiques s'esborren amb la instància. Abans d'eliminar, treu una instantània final.
- Canviar un paràmetre
pending-rebooti esperar que actuï. No fa res fins a reiniciar. - Restaurar i no executar
ANALYZE. Sense estadístiques, el planificador pren decisions pèssimes i sembla que RDS «va lent». - Posar la finestra de manteniment en hora punta. Diumenge de matinada, mai divendres a la tarda.
- Pujar de classe d'instància abans de mirar les consultes. Un índex que falta costa 0 USD al mes; una instància més gran, tots els mesos.
- Llegir de la rèplica el que l'usuari acaba d'escriure. El retard asíncron farà que de vegades no aparegui. Lectures crítiques, sempre a la principal.
- No provar mai una commutació per error. Provoca-la en un entorn de proves i comprova que l'aplicació es reconnecta. Descobrir-ho en producció surt car.
- Consell: activa Performance Insights des del primer dia. És gratis 7 dies i el dia que hi hagi una incidència voldràs tenir l'històric.
Exercicis
Exercici 1: dissenyar la topologia de bases de dades
MercadoFresco obre a tres ciutats més (problema 3). La previsió és:
- El pic dels divendres passa a 2.100 comandes/hora (escriptures intenses).
- La Sara passa d'un informe setmanal a un tauler que es refresca cada 15 minuts.
- Apareix un requisit nou: si es perd la regió
eu-west-1sencera, el negoci ha de poder operar en menys de 4 hores. - Es manté el requisit de no perdre cap comanda confirmada.
Dissenya la topologia de RDS: quines instàncies, de quin tipus, en quines AZ i regions, i quin mecanisme cobreix cada requisit. Indica quin requisit no pot cobrir RDS per si sol.
Exercici 2: recuperar d'un desastre amb PITR
El dijous a les 16:12, un script de sincronització de catàleg executa per error:
Ha esborrat 47.000 línies de comandes històriques que sí que eren vàlides. Ningú no se n'adona fins al divendres a les 10:30, quan la Sara veu que les xifres de juliol no quadren. En aquest temps s'han registrat unes 1.400 comandes noves que no es poden perdre.
Descriu el procediment complet de recuperació, amb les comandes, i explica per què no es pot simplement restaurar la base de dades al dijous a les 16:11.
Exercici 3: decidir on va cada consulta
Per a cada consulta de MercadoFresco, indica si ha d'anar a la instància principal o a la rèplica de lectura, i justifica-ho en una frase:
- A)
INSERTd'una comanda nova des de la cistella. - B) «Les meves comandes» d'un client que acaba de comprar fa 3 segons.
- C) Informe mensual de vendes agregades per barri.
- D) Llistat del catàleg de productes a la pàgina principal.
- E) Comprovació d'estoc just abans de confirmar una comanda.
- F) Exportació nocturna de totes les comandes a S3 per a analítica.
Solucions
Solució 1.
| Requisit | Solució | Detall |
|---|---|---|
| 2.100 comandes/h d'escriptura | Escalat vertical de la principal a db.m6g.xlarge (o migració a Aurora, lliçó 06-03) |
Les escriptures no es poden repartir entre rèpliques: només hi ha un escriptor. És el límit del model relacional clàssic |
| No perdre cap comanda confirmada | Multi-AZ a eu-west-1a / eu-west-1b |
Replicació síncrona: RPO = 0 |
| Tauler de la Sara cada 15 min | Rèplica de lectura db.r6g.large a eu-west-1b |
Família R per ser càrrega analítica intensiva en memòria; un retard de segons és irrellevant per a un tauler de 15 minuts |
| Sobreviure a la pèrdua de la regió | Rèplica de lectura a eu-central-1 + instantànies automàtiques copiades a aquesta regió |
Davant d'un desastre, es promou la rèplica a instància independent: minuts, molt per sota de les 4 hores exigides |
Topologia resultant:
eu-west-1a: mercadofresco-pedidos (principal, db.m6g.xlarge) eu-west-1b: instància en espera Multi-AZ (automàtica, no accessible) eu-west-1b: mercadofresco-pedidos-lectura (rèplica, db.r6g.large) → Sara eu-central-1: mercadofresco-pedidos-dr (rèplica entre regions) → recuperació davant de desastres
El que RDS no cobreix per si sol: el pic d'escriptures dels divendres continua depenent d'una sola instància escriptora. Escalar verticalment té un sostre. Les solucions reals són fora d'aquesta lliçó: encuar les comandes amb SQS per absorbir el pic i escriure-les a ritme sostingut (mòdul 7), posar les lectures calentes a la memòria cau amb ElastiCache (06-05), o repartir l'escriptura amb un model diferent de dades (DynamoDB, 06-02). Reconèixer aquest sostre és part de saber fer servir RDS.
Solució 2.
Per què no es pot restaurar sense més al dijous a les 16:11: això retornaria la base de dades a l'estat d'aquell instant, i amb això desapareixerien les 1.400 comandes registrades entre el dijous a la tarda i el divendres al matí. S'arreglaria un problema creant-ne un de pitjor. La restauració completa només val quan el dany es detecta en minuts.
El procediment correcte és restaurar en paral·lel i recuperar només el que s'ha esborrat:
# 1. Restaurar a una instància NOVA a l'instant anterior a l'esborrament.
# Producció continua funcionant sense assabentar-se'n.
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier mercadofresco-pedidos \
--target-db-instance-identifier mercadofresco-pedidos-rescate \
--restore-time 2026-08-06T16:11:00Z \
--db-subnet-group-name sng-mercadofresco \
--vpc-security-group-ids sg-0abc123def456 \
--no-publicly-accessible \
--db-instance-class db.t3.small \
--tags Key=Proyecto,Value=mercadofresco Key=Entorno,Value=pruebas \
Key=Componente,Value=pedidos Key=Propietario,Value=marta \
Key=CentroCoste,Value=operaciones \
--profile mercadofresco-dev --region eu-west-1
aws rds wait db-instance-available \
--db-instance-identifier mercadofresco-pedidos-rescate \
--profile mercadofresco-dev --region eu-west-1# 2. Extreure NOMÉS les files esborrades de la instància de rescat.
pg_dump -h mercadofresco-pedidos-rescate.abc123.eu-west-1.rds.amazonaws.com \
-U mfadmin -d pedidos \
--table=lineas_pedido --data-only --format=custom \
--file=lineas-rescate.dump-- 3. A PRODUCCIÓ: carregar l'abocament en una taula temporal i reinserir
-- únicament el que falta. ON CONFLICT protegeix de duplicar res.
CREATE TABLE lineas_pedido_rescate (LIKE lineas_pedido INCLUDING ALL);
-- (aquí es restaura l'abocament sobre lineas_pedido_rescate)
BEGIN;
INSERT INTO lineas_pedido
SELECT r.*
FROM lineas_pedido_rescate r
LEFT JOIN lineas_pedido a ON a.id = r.id
WHERE a.id IS NULL
ON CONFLICT (id) DO NOTHING;
-- Verificar ABANS de confirmar
SELECT count(*) FROM lineas_pedido; -- ha d'haver pujat ~47.000
COMMIT;
DROP TABLE lineas_pedido_rescate;# 4. Eliminar la instància de rescat per deixar de pagar-la
aws rds delete-db-instance \
--db-instance-identifier mercadofresco-pedidos-rescate \
--skip-final-snapshot \
--profile mercadofresco-dev --region eu-west-1Lliçons que deixa l'incident: el DELETE s'hauria d'haver executat dins d'una transacció amb
verificació prèvia del recompte; els scripts de manteniment no han de fer servir l'usuari mestre sinó
un rol amb permisos acotats (04-01); i una alarma sobre variacions brusques del nombre de files
hauria avisat el dijous i no el divendres.
Solució 3.
| Consulta | Destinació | Justificació |
|---|---|---|
A) INSERT de comanda |
Principal | És una escriptura. Les rèpliques són de només lectura, no hi ha alternativa |
| B) «Les meves comandes» després de comprar | Principal | El retard asíncron podria fer que la comanda acabada de crear no aparegués. Regla: el que l'usuari acaba d'escriure, es llegeix de la principal |
| C) Informe mensual per barri | Rèplica | Consulta pesada sobre dades històriques; uns segons de retard són irrellevants i així no castiga la botiga |
| D) Catàleg de la pàgina principal | Rèplica (i a més memòria cau) | Dades que canvien poc i es llegeixen moltíssim. El cas de manual per a una rèplica; amb ElastiCache al davant seria encara millor (06-05) |
| E) Estoc abans de confirmar | Principal | Dada crítica i volàtil: llegir un estoc desactualitzat provoca vendre producte que no existeix. A més sol necessitar bloqueig (SELECT ... FOR UPDATE), que només funciona a la principal |
| F) Exportació nocturna a S3 | Rèplica | Lectura massiva en horari vall; es fa a la rèplica precisament per no tocar la principal ni tan sols de nit, quan corren les còpies |
Patró general: escriptures i lectures crítiques o immediates → principal; lectures analítiques, històriques o tolerants al retard → rèplica.
Conclusió
La base de dades de comandes de MercadoFresco ja és a AWS, i amb ella el cor del negoci. Entens què significa un servei gestionat: AWS assumeix el maquinari, el sistema operatiu, els pedaços del motor, les còpies i la commutació per error; tu continues sent responsable de l'esquema, els índexs, les consultes i la seguretat de l'aplicació. Saps també a què renuncies a canvi —accés al sistema operatiu, superusuari real, extensions fora de llista— i en quins casos concrets això obliga a triar PostgreSQL sobre EC2 en comptes de RDS.
Has creat la instància mercadofresco-pedidos per consola i per CLI, amb les decisions que
importen preses conscientment: contrasenya gestionada a Secrets Manager per no escriure-la
mai, sense accés públic, xifratge activat, protecció contra eliminació, escalat automàtic
d'emmagatzematge, retenció de còpies de 7 dies i finestres de còpia i manteniment col·locades a la
vall de trànsit i mai un divendres a la tarda.
Has desfet el malentès més comú de RDS: la instància en espera de Multi-AZ no serveix trànsit. És una rèplica síncrona que garanteix zero pèrdua de dades i commuta en 60-120 segons canviant el DNS del punt d'enllaç, amb la contrapartida de sumar latència a cada escriptura i d'exigir que l'aplicació reintenti. Davant d'ella, les rèpliques de lectura són asíncrones, sí que es poden consultar i són l'eina correcta perquè el tauler de la Sara no castigui producció; has vist en codi i en taula quina consulta va a cada lloc.
I has tancat el problema 2 de MercadoFresco. Entre les instantànies d'EBS automatitzades amb DLM
de la lliçó 02-02, el versionatge d'S3 de la 02-03 i ara les còpies automàtiques de RDS amb
registres de transaccions cada cinc minuts, l'empresa ha passat d'«un pg_dump a un disc
extern quan algú se'n recorda» a poder restaurar a qualsevol segon dels últims set
dies. Has practicat la recuperació real d'un esborrament massiu restaurant en paral·lel i
reinserint només el que s'havia perdut, sense sacrificar les comandes posteriors. Hi sumes les instantànies
manuals que sobreviuen a l'esborrament de la instància, els grups de paràmetres amb
log_min_duration_statement i pg_stat_statements per caçar consultes lentes, Performance
Insights per saber en què espera realment la base de dades, la connexió des de l'aplicació sense
ni una sola credencial al codi, l'escalat vertical i d'emmagatzematge amb la seva regla d'or
—mira els índexs abans de pujar de classe— i el pla complet de migració amb pg_dump/pg_restore
i la seva alternativa sense aturada, AWS DMS.
Queda una última peça del mòdul. Tenim servidors que cal dimensionar, arrencar i pagar encara que estiguin ociosos. Però hi ha tasques de MercadoFresco que no necessiten un servidor esperant: generar la miniatura d'una foto quan es puja, respondre a una consulta puntual de l'estat d'una comanda, processar un fitxer. A la lliçó 02-05, «AWS Lambda», escriurem codi que s'executa només quan passa alguna cosa i només es paga mentre corre, connectarem per fi l'esdeveniment d'S3 que vam deixar configurat a 02-03 per generar les miniatures del catàleg, i recapitularem quines peces de MercadoFresco ja són al núvol i què falta per construir.
Curs d'AWS
Mòdul 1: Introducció a AWS
- Què és AWS?
- Configuració del teu compte d'AWS
- Infraestructura global d'AWS
- Consola d'administració d'AWS
- AWS CLI i SDK
Mòdul 2: Serveis principals d'AWS
Mòdul 3: Xarxes i lliurament de contingut
- Amazon VPC
- Grups de seguretat i llistes de control d'accés
- Elastic Load Balancing
- Amazon CloudFront
- Route 53
Mòdul 4: Seguretat i identitat
- AWS Identity and Access Management (IAM)
- AWS Key Management Service (KMS)
- Secrets Manager i Parameter Store
- AWS Shield
- AWS WAF
Mòdul 5: Monitoratge i gestió
- Amazon CloudWatch
- AWS X-Ray i traçabilitat distribuïda
- AWS CloudTrail
- AWS Config
- AWS Trusted Advisor
Mòdul 6: Bases de dades
- Com triar la base de dades adequada
- Amazon DynamoDB
- Amazon Aurora
- Amazon Redshift
- Amazon ElastiCache
Mòdul 7: Integració d'aplicacions
- Amazon SQS
- Amazon SNS
- Amazon EventBridge
- AWS Step Functions
- Patrons d'integració: idempotència, reintents i cues de missatges fallits
