The State API is a Key/Value database storage and the simplest way you can store some data in Drupal 8. One of its main purposes is to allow developers to store information that relates to the state of the system (hence the name). Also, because the state of the system can be interpreted in various ways, think of this as simple information related to the current environment (Drupal installation) that is not editorial (content), for example, a timestamp of the last time they ran or any flags or markers the system sets to keep track of its tasks. It is different from caching in that it is not meant to be cleared as often and only the code that set it is responsible for updating it.
One of the main characteristics of this system is the fact that it is not for human interaction. I mean this in the sense that it is the application itself that needs to make use of it. The option for humans is the configuration system that we will talk about in detail in a later section. However, in quite a few cases, the latter falls short, and we need to (and it's perfectly acceptable) use the State system in order to store certain values input by an administrator or content editor through a form in the UI. That is because these values are of the same nature as those for which the State API is designed: they relate to only this environment, don't belong in code, and work together with the system to perform certain tasks, for example, an API key for an external service or a toggle value to enable/disable a subsystem. So, for this reason, the State API is great. There is, however, active work going on around the configuration API that would allow an easy separation between what is exportable to code and what is not. However, until then, the State API gets us covered.
So now that we know about the State API, let's jump into the technicalities and see what it's made of and how we can use it.
The State system revolves around the StateInterface, which provides all the methods you need to interact with it. This interface is implemented by the State service, which we can inject into your classes or use statically via the \Drupal::state() shorthand. Once we have that, things could not be any easier, as the interface tells you exactly what we can do.
We can set a value, as follows:
\Drupal::state()->set('my_unique_key_name', 'value');
Alternatively, we can get a value:
$value = \Drupal::state()->get('my_unique_key_name');
We can also set/get multiple values at once (how convenient!):
\Drupal::state()->setMultiple(['my_unique_key_one' => 'value', 'my_unique_key_two' => 'value']);
$values = \Drupal::state()->getMultiple(['my_unique_key_one', 'my_unique_key_two']);
Isn't that easy? You can also, of course, get rid of them:
\Drupal::state()->delete('my_unique_key_name');
\Drupal::state()->deleteMultiple(['my_unique_key_one', 'my_unique_key_two']);
There are a couple of things to note here. First, the key names you choose live in a single namespace, so it's recommended that you prefix them with your module name--my_module.my_key. That way, you avoid collision. Second, the values you store can also be more complex than simple strings. You can store any scalar value, but also objects, as they get serialized and deserialized automatically. Be careful, though, about which objects you plan on storing. Never ever store objects that have container dependencies and do make sure that any classed objects you dump in there serialize and deserialize properly.
By now, you are probably wondering where these values end up. They go into the key_value table, namespaced under the state collection. Also, the latter is a nice segue into a talk about the underlying system that powers the State API--the Key/Value store.
Note that the State system is only one implementation of an underlying framework of Key/Value stores. If you look at the State service, you will note that it uses the KeyValueFactoryInterface (which by default is implemented by the KeyValueDatabaseFactory). This, in turn, creates a Key/Value storage instance (by default, the DatabaseStorage), which provides the public API to interact with the store. If you take a look at the key_value table in the database, you'll note other collections besides state. Those are other implementations specific to various subsystems, such as the Entity API and System schema. Guess what, you can easily write your own and customize it to your needs. However, the reason why the State API was created was so that module developers can use it. Also, valid uses of it cover much of the need for something such as a Key/Value store. So, odds are that you won't have to implement your own.