Obsidian uses its own native ORM and HikariCP for connection pooling. The connection is managed automatically — no manual wrapping required.
| Database | DB_TYPE | Notes |
|---|---|---|
| SQLite | sqlite | File-based, no pooling. Perfect for development and small apps. |
| MySQL | mysql | HikariCP connection pooling included. SSL enabled by default. |
| PostgreSQL | postgresql | HikariCP connection pooling included. SSL enabled by default. |
Obsidian uses dotenv-java to load credentials from a .env file at your project root.
ENVIRONMENT=development
PORT_WEB=8080
DB_TYPE=sqlite
DB_PATH=database.db
ENVIRONMENT=development
PORT_WEB=8080
DB_TYPE=mysql
DB_HOST=localhost
DB_PORT=3306
DB_NAME=my_database
DB_USER=root
DB_PASSWORD=secret
ENVIRONMENT=development
PORT_WEB=8080
DB_TYPE=postgresql
DB_HOST=localhost
DB_PORT=5432
DB_NAME=my_database
DB_USER=postgres
DB_PASSWORD=secret
.env file to version control. Add it to .gitignore.SSL is enabled by default for MySQL and PostgreSQL. In local dev or test environments where your server has no certificate, disable it via an environment variable or a JVM system property.
OBSIDIAN_DB_DISABLE_SSL=true
-DOBSIDIAN_DB_DISABLE_SSL=true
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<systemProperties>
<systemProperty>
<key>OBSIDIAN_DB_DISABLE_SSL</key>
<value>true</value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>
The framework automatically opens and closes the thread-local connection around every HTTP request via two built-in middlewares — DatabaseMiddleware and DatabaseCloseMiddleware. You never need to manage connections manually in controllers or repositories.
When running database queries outside of an HTTP request (e.g. in a LiveComponent or a background task), wrap the call with DB.withConnection():
List<UserDTO> users = DB.withConnection(() ->
userService.findAll().stream().toList()
);
Use DB.withTransaction() for atomic operations. Changes are committed on success and rolled back on any exception.
DB.withTransaction(() -> {
User sender = Model.find(User.class, senderId);
User receiver = Model.find(User.class, receiverId);
if (sender.getBigDecimal("balance").compareTo(amount) < 0) {
throw new IllegalStateException("Insufficient balance");
}
sender.set("balance", sender.getBigDecimal("balance").subtract(amount));
receiver.set("balance", receiver.getBigDecimal("balance").add(amount));
sender.save();
receiver.save();
return true;
});
HikariCP is automatically configured with these defaults:
| Maximum pool size | 20 connections |
| Minimum idle | 5 connections |
| Connection timeout | 30 seconds |
| Idle timeout | 10 minutes |
| Max lifetime | 30 minutes |
SQLite uses direct JDBC connections without pooling.