Overview
The Inmobiliaria API uses PostgreSQL as its database and Drizzle ORM for type-safe database access and migrations.Requirements
- PostgreSQL 12 or higher
- Node.js 18 or higher
- Database with
publicschema access
Quick Setup
Set DATABASE_URL
Add the connection string to your Format:
.env file:.env
postgresql://[user]:[password]@[host]:[port]/[database]Drizzle Configuration
The database is configured indrizzle.config.ts:
drizzle.config.ts
Configuration Options
| Option | Value | Description |
|---|---|---|
out | ./src/db/migrations | Directory for migration files |
schema | ./src/db/schema/* | Drizzle schema definition files |
dialect | postgresql | Database type |
schemaFilter | ["public"] | Use PostgreSQL public schema |
verbose | true | Show detailed migration logs |
strict | true | Enable strict mode for schema validation |
Database Schema
The application uses a comprehensive schema organized into several domains.Authentication Tables
users
users
Core user accounts table (Better Auth compatible).Schema Definition:
src/db/schema/users.ts| Column | Type | Description |
|---|---|---|
id | text | Primary key (UUID) |
name | text | User’s display name |
email | text | Unique email address |
email_verified | boolean | Email verification status |
image | text | Profile image URL |
role | user_role | user or admin |
created_at | timestamp | Account creation time |
updated_at | timestamp | Last update time |
sessions
sessions
Active user sessions.
| Column | Type | Description |
|---|---|---|
id | text | Primary key |
user_id | text | References users.id |
token | text | Unique session token |
expires_at | timestamp | Session expiration |
ip_address | text | Client IP |
user_agent | text | Browser/device info |
accounts
accounts
OAuth provider accounts linked to users.
| Column | Type | Description |
|---|---|---|
id | text | Primary key |
user_id | text | References users.id |
provider_id | text | OAuth provider (google, etc.) |
account_id | text | Provider’s user ID |
access_token | text | OAuth access token |
refresh_token | text | OAuth refresh token |
verification
verification
Email verification tokens.
| Column | Type | Description |
|---|---|---|
id | text | Primary key |
identifier | text | Email or user identifier |
value | text | Verification token |
expires_at | timestamp | Token expiration |
Property Management Tables
properties
properties
Main properties listing table.Schema Definition:
src/db/schema/properties.tsKey Columns:- Basic info:
title,description,url_slug - Classification:
property_type_id,property_subtype_id,operation_type_id - Pricing:
price,original_price,currency_id,expenses - Size:
surface_covered_m2,surface_uncovered_m2,lot_size_m2 - Rooms:
rooms,bedrooms,bathrooms - Features:
has_balcony,has_terrace,has_garden,garage_spaces - Status:
status_id,published_at,views_count - Ownership:
user_id
- References multiple metadata tables
- One-to-one with
property_locations - One-to-many with
property_images
property_locations
property_locations
Property address and geolocation.
| Column | Type | Description |
|---|---|---|
property_id | integer | References properties.id (unique) |
street | varchar | Street name |
street_number | varchar | Street number |
neighborhood | varchar | Neighborhood/barrio |
city | varchar | City name |
province | varchar | Province/state |
latitude | decimal(10,7) | GPS latitude |
longitude | decimal(10,7) | GPS longitude |
show_exact_address | boolean | Privacy control |
property_images
property_images
Property photos with variants.
| Column | Type | Description |
|---|---|---|
property_id | integer | References properties.id |
image_key | text | Storage key (main variant) |
image_url | text | Public URL |
order_index | integer | Display order |
is_main | boolean | Featured image flag |
rotation_degrees | integer | 0, 90, 180, or 270 |
Images are stored with variants:
-lg.webp (large) and -thumb.webp (thumbnail).Metadata Tables
property_types
property_types
Property categories (Casa, Departamento, etc.).Pre-populated with: 14 types including Casa, Departamento, PH, Terreno, Local comercial, etc.
| Column | Type | Description |
|---|---|---|
id | serial | Primary key |
name | varchar | Display name |
slug | varchar | URL-friendly identifier |
property_subtypes
property_subtypes
Subcategories within property types.Examples: Casa en country, Monoambiente, PH con jardín
| Column | Type | Description |
|---|---|---|
id | serial | Primary key |
type_id | integer | References property_types.id |
name | varchar | Display name |
slug | varchar | URL-friendly identifier |
operation_types
operation_types
Transaction types: Venta, Alquiler, Alquiler temporal, Permuta.
property_statuses
property_statuses
Status: Activo, Pendiente, Vendido, Alquilado, Pausado.
property_conditions
property_conditions
Condition: A estrenar, Bueno, Muy bueno, Excelente, Reciclado, Para refaccionar.
currencies
currencies
Supported currencies: ARS (Peso Argentino), USD (Dólar), EUR (Euro).
Property Characteristics
property_characteristics_all
property_characteristics_all
Unified characteristics table supporting both predefined and custom features.
Constraints:
| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
property_id | integer | References properties.id |
label | varchar(150) | Characteristic name |
created_at | timestamp | When added |
- Unique per property (case-insensitive, trimmed)
- Label length: 1-150 characters
Contact & Engagement
contact_requests
contact_requests
Property valuation and contact form submissions.Schema Definition:
src/db/schema/contact.ts| Column | Type | Description |
|---|---|---|
id | uuid | Primary key |
name | varchar | Contact name |
email | varchar | Contact email |
phone | varchar | Contact phone |
available_hours | varchar | Preferred contact time |
operation_type | varchar | Venta/Alquiler |
property_type | varchar | Type of property |
location | text | Property location |
description | text | Details |
status | enum | pending/contacted/completed |
user_id | text | Optional linked user |
is_deleted | boolean | Soft delete flag |
user_favorites
user_favorites
User saved properties.
Constraint: Unique per user-property pair
| Column | Type | Description |
|---|---|---|
id | serial | Primary key |
user_id | text | References users.id |
property_id | integer | References properties.id |
created_at | timestamp | When favorited |
Database Scripts
Available npm scripts for database management:package.json
Command Reference
Connection Configuration
The database connection is configured insrc/db/index.ts:
src/db/index.ts
Connection Pooling
The application usespg connection pooling with defaults:
- Max connections: 10 (pg default)
- Idle timeout: 10 seconds
- Connection timeout: 0 (no timeout)
Health Checks
The API includes database health check endpoints:Production Considerations
SSL Connections
SSL Connections
Enable SSL for production databases:The application automatically detects
sslmode=require and configures SSL.Connection Limits
Connection Limits
- Monitor active connections
- Configure
maxpool size based on load - Use connection pooling services (PgBouncer) for high traffic
- Most cloud providers (Heroku, Render) include connection pooling
Migrations
Migrations
Development:Production:
- Always use migrations in production
- Review generated SQL before applying
- Backup database before major migrations
Backups
Backups
Regular backup strategies:Automated: Use your hosting provider’s backup features
Indexes
Indexes
The schema includes performance indexes:
idx_sessions_token- Fast session lookupsidx_sessions_user_id- User’s sessionsidx_properties_type- Filter by property typeidx_properties_operation- Filter by operationidx_locations_city- Location-based searchidx_properties_search- Full-text search (GIN index)
Troubleshooting
Connection Refused
Connection Refused
Error:
ECONNREFUSED or “Connection refused”Solutions:- Verify PostgreSQL is running:
pg_isready - Check host/port in
DATABASE_URL - Verify firewall allows connections
- For Docker: check container is running
Authentication Failed
Authentication Failed
Error: “password authentication failed”Solutions:
- Verify username and password in
DATABASE_URL - Check
pg_hba.confauthentication method - Reset password:
ALTER USER postgres PASSWORD 'newpassword';
Database Does Not Exist
Database Does Not Exist
Error: ‘database “inmobiliaria” does not exist’Solution:
Schema/Table Not Found
Schema/Table Not Found
Error: ‘relation “users” does not exist’Solutions:
- Run migrations:
npm run db:pushornpm run db:migrate:run - Verify
schemaFilter: ["public"]in drizzle.config.ts - Check search_path:
SHOW search_path;
Too Many Connections
Too Many Connections
Error: “sorry, too many clients already”Solutions:
- Reduce pool
maxconnections - Close idle connections
- Increase PostgreSQL
max_connections - Use connection pooling service (PgBouncer)
See Also
- Environment Variables - Required database configuration
- Storage Configuration - File upload setup
- API Reference - Database-backed endpoints