DynamoDB Session Handler
Aws.DynamoDbSession stores the sessions in a DynamoDB table with Aws\DynamoDb\SessionHandler. Configure it in config/core.php (legacy layout: app/Config/core.php):
Configure::write('Session', [
'defaults' => 'php',
'cookie' => 'MY_APP',
'handler' => [
'engine' => 'Aws.DynamoDbSession',
'table_name' => 'DYNAMODB_TABLE_NAME',
// Optional: other options of Aws\DynamoDb\SessionHandler (default: 'locking' => true)
// 'locking' => true,
],
// Minutes; also the lifetime written to the "expires" attribute of each item
'timeout' => 1440,
'ini' => [
'session.cookie_lifetime' => 0,
// Expired sessions are removed by DynamoDB's Time to Live, not by PHP's garbage collection
'session.gc_probability' => 0,
],
]);handler.table_nameis required; aCakeExceptionis thrown when it is missing.- The other keys of
handler(exceptengine) are passed to the SDK's session handler, for examplelocking,session_lifetimeorconsistent_read. Session locking is enabled unless you set'locking' => false. session_lifetimeis the number of seconds until a session expires. It defaults toSession.timeoutminutes, the timeout thatCakeSessionchecks, so a session item expires together with the session. WithoutSession.timeout, it defaults tosession.gc_maxlifetime.- The table must exist, with a string partition key named
id, and Time to Live must be enabled on theexpiresattribute (see Creating the Session Table). - The DynamoDB client is created with the
Awsconfiguration, so the plugin must be loaded andAwsconfigured before the session starts. - If several applications share a domain and a table, give each application its own session cookie name (
Session.cookie) so that they do not read each other's sessions.
The items are those of the AWS SDK's session handler: the key is <session name>_<session id>, the data is a string, the expiration time is a Unix timestamp in expires, and a lock attribute marks a locked session. pieceofcake2/async-aws writes the same items, so both plugins can use the same table.
Creating the Session Table
Create the table and enable Time to Live on the expires attribute with the AWS CLI:
aws dynamodb create-table --table-name DYNAMODB_TABLE_NAME \
--attribute-definitions AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
aws dynamodb update-time-to-live --table-name DYNAMODB_TABLE_NAME \
--time-to-live-specification "Enabled=true,AttributeName=expires"How Sessions Expire
DynamoDB removes the expired sessions itself:
- Each write and close of a session stores its expiration time, the current time plus
session_lifetime, in theexpiresattribute. - DynamoDB's Time to Live deletes the items whose
expirestime has passed. It runs in the background at no cost but lazily: an expired item can stay in the table for up to about 48 hours, sometimes longer. - Until then, the handler reads an expired session as an empty session without deleting it, and the next write of that session replaces the old data. An expired session never comes back.
PHP's session garbage collection is off: the example sets session.gc_probability to 0, and DynamoDbSession also sets it to 0 when Session.ini does not contain session.gc_probability.
Garbage Collection
DynamoDbSession::gc() can still delete the expired sessions, for tables without Time to Live. It scans the whole table for items whose expires time has passed and deletes them with BatchWriteItem (25 items per request, retrying unprocessed items a few times). Errors are logged with the session scope and never interrupt the request.
A scan reads, and is charged for, every item of the table, and runs during the request that PHP picks for garbage collection, so keep it off when Time to Live is enabled. To turn it on, set the probability in Session.ini, for example once every 1000 session starts:
Configure::write('Session', [
// ...
'ini' => [
'session.cookie_lifetime' => 0,
'session.gc_probability' => 1,
'session.gc_divisor' => 1000,
],
]);The SDK's SessionHandler::garbageCollect() uses the same deletion.
DynamoDB Local
DynamoDB Local accepts the Time to Live setting, but whether it deletes expired items depends on its version (the current amazon/dynamodb-local image does). Expired sessions are always read as empty; if they stay in the table, delete them by hand or turn on garbage collection in local development as shown above.
The SDK's session handler sends UpdateItem requests without an Action, relying on the PUT default of DynamoDB, which DynamoDB Local does not apply. DynamoDbSession adds 'Action' => 'PUT' to these requests, so sessions are stored in DynamoDB Local as well.
