# Athena ORM Alpha Version - Testers wanted!

**URL:** <https://forum.crystal-lang.org/t/athena-orm-alpha-version-testers-wanted/8904>\
**Category:** Community\
**Created:** [April 26, 2026, 4:40am UTC](https://forum.crystal-lang.org/t/athena-orm-alpha-version-testers-wanted/8904 "2026-04-26T04:40:51Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [April 26, 2026, 4:40am UTC](https://forum.crystal-lang.org/t/athena-orm-alpha-version-testers-wanted/8904/1 "2026-04-26T04:40:51Z")

</div>

In addition to [Athena 0.22.0 | Now with real-time updates!](https://forum.crystal-lang.org/t/athena-0-22-0-now-with-real-time-updates/8903), I have another surprise I’m excited to share. After years of on and off again work, the Athena ORM is now in a state that is functional/usable enough to start gathering feedback. The [`demo.cr` file](https://github.com/athena-framework/orm/blob/develop/examples/demo.cr) on the `develop` branch serves as a good example of what its usage looks like in practice.

Unlike other ORMs in Crystal land at the moment, it has a few unique qualities:

- No custom DSL, entities (models) are normal Crystal classes the use annotations on properties to apply DB related metadata (columns, relationships, PKs, etc).
- Data-Mapper instead of ActiveRecord, a separate service is used to manage entities; e.g. persisting, querying, etc.
  - This has some benefits like smarter queries, query batching, and powerful change detection. E.g. when updating an entity only changed values are included in the `UPDATE` query.

- Built-in native relationships/lazy loading, relationships are handled essentially as a `Array(T)` whose contents are not loaded until the collection is interacted with.
- Repository pattern, simple/one-off queries can handled via basic `find`, `find_all`, `find_by`, `find_one_by` methods, while more complex/reusable/specialized queries can be abstracted to a Repository type that provides better type safety/documentation.

However, as I mentioned, this is still in an Alpha state, so nothing is really set in stone. There are a few things on my near-term list that I am aware of at the moment:

- It’s lacking on the query side of things. `find_by` works enough for simple things, but isn’t really all that type safe nor sufficient to handle more complex queries/joins/etc
  - Some type of QueryBuilder is on the list, but is of course not small feat
  - I do have some ideas on improving type saftey of queries tho, so stay tuned!
  - `NativeQuery` is a somewhat verbose but useable escape hatch that can handle more complex/arbitrary SQL
  - EDIT: It’s also possible access the raw `DB::Connection` instance to use DB API directly

- How to best use it outside of an Athena context. It’s expected there is a single shared `EntityManager` per-request if in a web context for example. I have some ideas for how to go about this, but want some actual examples of how DBs are used in existing projects, esp those using `DB::Serializable` and not an actual ORM before committing
- Limited platform/column type support, I have the basics and plan to add more of both in the future
- No testing utilities as of now
- No migration support as of now
- Bugs, there are probably quite a few of them at this point

What I ultimately would like now is for you all to try it for your use cases to identity any bugs, rough edges, our missing features that you run into in the process. Feel free to ping me in this thread, in the Crystal or [Athena](https://discord.gg/TmDVPb3dmr) Discord server to chat more about it!

---

<div class="post-metadata">

**Author:** ![yxhuvud](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/yxhuvud/32/27_2.png) [@yxhuvud](https://forum.crystal-lang.org/u/yxhuvud)\
**Post date:** [April 26, 2026, 9:10am UTC](https://forum.crystal-lang.org/t/athena-orm-alpha-version-testers-wanted/8904/2 "2026-04-26T09:10:50Z")

</div>

> [@Blacksmoke16](#):
>
> Data-Mapper instead of ActiveRecord, a separate service is used to manage entities; e.g. persisting, querying, etc.
> 
> - This has some benefits like smarter queries, query batching, and powerful change detection. E.g. when updating an entity only changed values are included in the `UPDATE` query.

Nice, though at least when it comes to only updating changed values, nothing stops good ActiveRecord implementations from doing the same.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [May 7, 2026, 5:44pm UTC](https://forum.crystal-lang.org/t/athena-orm-alpha-version-testers-wanted/8904/3 "2026-05-07T17:44:42Z")

</div>

Have made some more progress and think I’m getting close to at least getting off the `develop` branch. Some of the new highlights:

## Entity Proxies

```crystal
class User < AORM::Entity
  # ...
  @[AORMA::OneToOne]
  property avatar! : AORM::Proxy(Avatar)
end

```

In order to combat `N+1` queries/eager loads, `ToOne` relationship properties may be typed as the new `AORM::Proxy` type. This will make so when you load the entity, say via `user = em.find! User, 1`, that a proxy obj is used as the value of the relationship ivar instead of making a query for the real value. This allows you to do things like `user.avatar.id # => 321` without making a query, but if you did `user.avatar.url` that would trigger a query once to populate the actual `Avatar` entity.

If the type of the property is `Avatar` itself, then anytime the `User` entity is loaded, its `Avatar` will be eagerly loaded as well.

## RETURNING

_Most_ databases today support `RETURNING` within `INSERT` statements in order to return the PK(s) of the newly inserted record. The ORM component now will use this more robust method when supported by the underlying DB. It’ll still fallback on `SELECT LAST_INSERT_ID();` (or equivalent) if needed.

## Eventing

There is now initial support for defining both lifecycle callbacks and entity-specific/global event listeners. The former can be useful for setting `created_at`/`updated_at` timestamp values in an opt-in basis. While event listeners can be used to implement more custom logic for a given entity type, or all entities. For example:

```cr
@[AORMA::PrePersist]
# :nodoc:
def set_created_at : Nil
  @created_at = Time.utc
end

```

Most commonly this could be be a part of a `CreatedAtAware` module that could define the getter and this callback function and simply included into entities that need this behavior. A similar setup could be done for `updated_at`, or similar columns.

### Event Listeners

For more complex logic, there will an optional [Athena::EventDispatcher](https://athenaframework.org/EventDispatcher/) integration

```crystal
class MyEntityListener
  # Only invoked when a new `Avatar` entity instance is persisted.
  @[AEDA::AsEventListener]
  def only_avatars(event : PrePersist(Avatar)) : Nil
    # ...
  end
  
  # Invoked when _any_ new entity instance is persisted.
  @[AEDA::AsEventListener]
  def any_entity(event : PrePersist(AORM::Entity)) : Nil
    # ...
  end
end

```

These can be useful as an alternative to DB triggers, and to allow for event based logic such as sending an email when a new user is created anywhere in the app, etc.

### Misc

- Add support for `Time` columns
- More test coverage
- Fix bugs
- Improve compile time perf

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [October 5, 2026, 1:55am UTC](https://forum.crystal-lang.org/t/athena-orm-alpha-version-testers-wanted/8904/4 "2026-10-05T01:55:25Z")

</div>

Been a while since my last update, and haven’t been keeping track of changes all that well, but this is getting to be in a fairly solid spot at the moment. Hoping to have at least an initial release somewhat soon 🤞. Still could do with some testers tho!
