Aruuri's database architecture is built for trust, transparency, and scalability, leveraging **Drizzle ORM** for type-safe interactions with **Neon PostgreSQL** as its serverless relational database.
Updated November 7, 2025
Page Viewers
171
0 users~171 guests
Guest Views
~171 views from anonymous visitors
v1
Database Architecture & Domain Separation
Aruuri's database architecture is built for trust, transparency, and scalability, leveraging Drizzle ORM for type-safe interactions with Neon PostgreSQL as its serverless relational database. This foundation adheres to a domain-driven design approach, ensuring clear separation of concerns, improved maintainability, and readiness for complex query patterns or event sourcing (CQRS). For a broader understanding of the monorepo structure, refer to the [Aruuri Monorepo Architecture] page.
Domain-Driven Database Separation
To achieve maximum organizational clarity and enable independent scaling and development for different parts of the platform, Aruuri employs a multi-database strategy, with each database corresponding to a specific business domain. This approach isolates critical data and logic, preventing tight coupling and simplifying data management.
The four core database domains are:
Platform Database: Manages the core infrastructure of the platform.
Purpose: Stores fundamental user data, authentication details, global platform settings, and audit logs.
Projects Database: Handles the lifecycle and details of community projects.
Purpose: Stores data related to funding themes, organizational missions, partner information, individual projects, funding stages, and project milestones.
Finance Database: Manages all financial transactions and accounting.
Purpose: Stores records of contributors, contributions, allocations, disbursements, payment processor fees, Gift Aid declarations, claims, and the double-entry accounting ledger (accounts, journals, entries).
Content Database: Stores all content managed by the CMS.
Purpose: Stores editorial content such as blog posts, static pages, media assets, categories, general CMS settings, and CMS user data, including project-specific, partner-specific, and mission-specific content details.
Each domain's database clients and schema definitions are encapsulated within the packages/database directory, promoting a "monorepo native" shared package approach that is consumed by various applications.
Key Features
The database layer incorporates several modern features to ensure robustness and developer efficiency:
Type Safety: Full TypeScript support with Drizzle ORM ensures that database interactions are type-checked at compile time, catching errors early and enhancing code reliability.
Serverless Optimized: Utilizes Neon's HTTP driver, which is optimized for serverless environments like Next.js edge and AWS Lambda, enabling efficient and scalable database access without persistent connections.
Database Branching: Leverages Neon's database branching capabilities, providing isolated development branches for each pull request. This allows for safe, concurrent experimentation and schema changes without impacting other environments.
Schema Management: Drizzle Kit is used for managing schema definitions and generating database migrations, ensuring controlled and versioned schema evolution.
Developer Experience: Integration with Drizzle Studio provides a visual interface for exploring schemas, querying data, and managing migrations, significantly improving developer productivity.
Database Clients & Connection Management
The packages/database/src/client.ts module centralizes the instantiation of database clients for each domain. It differentiates between various connection types to optimize performance and resource utilization:
Pooled Connections: For application queries and read-heavy operations, ARUURI_{DOMAIN}_DATABASE_URL_POOLED environment variables are used. These point to a connection pooler (like Neon's serverless driver) to efficiently manage database connections in stateless environments.
Direct Connections: For administrative tasks such as running migrations, ARUURI_{DOMAIN}_DATABASE_URL is used, providing a direct connection to the database.
Read Replicas: Optional ARUURI_{DOMAIN}_DATABASE_URL_READ variables allow for dedicated read replicas. If a read replica is configured, a separate client ({domain}DbRead) is provided; otherwise, it gracefully falls back to the primary pooled connection.
Example Client Instantiation (from packages/database/src/client.ts)
Quick Start
To set up and interact with the local development database:
Navigate to the database package:
Set up your local development branch (creates a new Neon branch):
Add test data to your local branch (currently disabled, see note below):
Open Drizzle Studio for visual database management:
Push schema changes (applies migrations):
Note: The pnpm dev:db:seed script is currently disabled as the initial database schemas are still under development. It will be re-enabled once core table structures are finalized.
Usage Example
Interacting with the database is type-safe and intuitive, thanks to Drizzle ORM: