diff --git a/pom.xml b/pom.xml
index aab1aee..008811f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -60,6 +60,10 @@
io.quarkus
quarkus-jdbc-h2
+
+ io.quarkus
+ quarkus-flyway
+
io.quarkus
quarkus-smallrye-jwt
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 199dabd..70803db 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -8,8 +8,12 @@ quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:file:./data/shots;DB_CLOSE_DELAY=-1
quarkus.datasource.username=sa
quarkus.datasource.password=
-quarkus.hibernate-orm.database.generation=create-drop
+quarkus.hibernate-orm.database.generation=validate
quarkus.hibernate-orm.log.sql=false
+# Flyway maneja el schema. validate hace que Hibernate solo valide
+# que el schema en DB coincide con las entities, sin tocarlo.
+quarkus.flyway.migrate-at-start=true
+quarkus.flyway.baseline-on-migrate=true
# JWT
mp.jwt.verify.issuer=shot-crafter-calculator
diff --git a/src/main/resources/db/migration/V1__init.sql b/src/main/resources/db/migration/V1__init.sql
new file mode 100644
index 0000000..98f7d28
--- /dev/null
+++ b/src/main/resources/db/migration/V1__init.sql
@@ -0,0 +1,32 @@
+CREATE TABLE users (
+ id UUID PRIMARY KEY,
+ username VARCHAR(30) NOT NULL UNIQUE,
+ password_hash VARCHAR(100) NOT NULL,
+ created_at TIMESTAMP NOT NULL,
+ must_change_password BOOLEAN NOT NULL,
+ is_admin BOOLEAN NOT NULL,
+ last_login_at TIMESTAMP
+);
+
+CREATE TABLE user_state (
+ user_id UUID PRIMARY KEY,
+ state_json TEXT NOT NULL,
+ updated_at TIMESTAMP NOT NULL
+);
+
+CREATE TABLE production_runs (
+ id UUID PRIMARY KEY,
+ user_id UUID NOT NULL,
+ created_at TIMESTAMP NOT NULL,
+ label VARCHAR(100),
+ total_cost BIGINT NOT NULL,
+ total_sale BIGINT NOT NULL,
+ total_profit BIGINT NOT NULL,
+ total_shots BIGINT NOT NULL,
+ total_cristales_used BIGINT NOT NULL,
+ total_ore_used BIGINT NOT NULL,
+ items_json TEXT NOT NULL,
+ snapshot_json TEXT NOT NULL
+);
+
+CREATE INDEX idx_runs_user_created ON production_runs (user_id, created_at);