Programming model

Akka Serverless lets developers focus on their API first, by letting them create the data objects that make sense for their service without needing to know how that data needs to be persisted in the durable storage. The services that you create can contain both stateful and stateless components. For stateful components, you choose a state model and Akka Serverless handles the data management for you.

What is an Akka Serverless service?

In Akka Serverless, a "service" is the code you write to implement your functionality and package up to run in Akka Serverless. An Akka Serverless service can contain one or more components, like stateless Actions, stateful Entities, and Views:

  • Entities are domain objects that encapsulate data and business logic. For example, in a weather monitoring IoT application, an entity might be a digital twin with an ID, data fields to keep track of temperature, air quality, and other weather related data. For each entity, you choose a state model, which determines how Akka Serverless manages the data.

  • Actions contain logic that does not need to persist state. For example, an Action can transform incoming data if required, or listen to published events.

  • Views allow you to retrieve data from multiple entities. Create Views using a SQL-like query language.

In Akka Serverless development we use the term entity as it is used in domain-driven design, specifically an aggregate root. An understanding of domain-driven design is beneficial but not necessary to work with Akka Serverless.

A service can have multiple components (like Views, Actions, and Entities)Services can only be invoked by messages. Services can receive those messages over gRPC, over HTTP, or by subscribing to topics. Clients, like user interfaces, other services, or external systems that send messages to a service can be built using any framework that you choose.

How does Akka Serverless manage state?

In more traditional software architectures, you usually have an application tier that uses a database tier to retrieve and store data. This type of architecture puts a lot of extra burden on DevOps teams, because they:

  • Need to know things like how to connect to the database, how it behaves, and which tables are needed to develop their services.

  • Need to maintain versions and compatibility across releases of both their services and the underlying infrastructure.

  • Need to build additional components to handle errors and deal with transactional failures.

  • Need to scale databases as their system grows to accommodate for the extra database connections of new services.

Every service in Akka Serverless has a proxy. This proxy acts as an in-memory data store (which removes the need to cache data separately), and is backed by durable storage to make sure you never lose data. By keeping the data in-memory, Akka Serverless reduces latency for data-centric operations. That means that Akka Serverless handles all your data access, transactional concerns, and scalability without a developer having to know which tables are needed, how the data is persisted, or even what kind of database is used. All the functionality for concurrent updates, caching, sharding (distributing across nodes), and routing is handled by the Akka Serverless proxy. The proxy also makes sure that your service gets the data it needs at the time it needs the data. This simplifies your code. When the service is deployed Akka Serverless handles state, avoids contention for resources, and supports scaling and failover, resulting in an elastic and resilient system.

At runtime, when a client makes a request to your service, the request is received by the API endpoints you configure in your service and is forwarded to the Akka Serverless proxy. The proxy looks up the right instance of the entity and forwards the request and the entity instance to your service.

The following diagram illustrates the Akka Serverless architecture at runtime:

runtime interaction

What are you responsible for implementing?

While Akka Serverless takes care of data persistence and retrieval, you write the code that encapsulates the state and business logic. That means you’ll provide the implementation for Entities, Actions, and Views. Each instance of an entity has a unique identifier (a key) that Akka Serverless uses to send your service the right instance at the right time. For example, an entity instance might represent a device in an IoT application (with the unique identifier being a serial number), a customer in a banking application (with the unique identifier being the bank account number), or a shopping cart in a retail application (with the unique identifier being the customer number).

Entities have the following attributes:

Attribute Description Example

A state model determines how Akka Serverless stores data.

For example, Value Entities only store the latest state (similar to a Key/Value store) and Event Sourced Entities persist each change in state as an event stored in a journal (The journal can be used to replay events to reconstruct state at a particular time, debug, or provide an audit).

A unique key.

At runtime, this unique key distinguishes each Entity instance from all others. The key can be multi-part, consisting of multiple items.

Examples of unique keys for entities are address (for houses), serial number (for machines), or customer number (for people).

One or more data fields.

Data fields represent all the data you want to keep track of for your entity.

Examples are temperature and air quality for weather systems, name and inventory for products in a warehouse, or email address and phone number for customers in a retail application

One or more operations.

These operations, which come in the form of commands, can change the state of your entity and are called by your clients. The business logic you write implements these operations.

Examples are UpdateTemperature, AddInventory, or SetEmailAddress

For example, you might create a Home service that manages a House entity. It needs a unique identifier such as a house id, which might include address, and phone number. It will have other data items such as furniture, appliances, temperature, residents, and visitors. It has operations that can change its state such as adding or removing a resident. It can refer to other Entities. And it can contain sets of other data, such as when a resident has multiple visitors.