final public function create(DynamoDbClient $client, string $tableName): void
    {
        try {
            $client->describeTable(['TableName' => $tableName]);
            return;
        } catch (DynamoDbException $e) {
            // table doesn't exist, create it below
        }

        $this->loadIndexes();

        $attributes = [];
        $indexes = [];

        foreach ($this->gsi as $gsi) {
            foreach ($gsi->getKeyAttributes() as $definition) {
                $attributes[$definition['AttributeName']] = $definition;
            }

            $indexName = $gsi->getName();
            $indexes[$indexName] = [
                'IndexName'             => $indexName,
                'KeySchema'             => [
                    ['AttributeName' => $gsi->getHashKeyName(), 'KeyType' => 'HASH'],
                ],
                'Projection'            => $gsi->getProjection() ?: ['ProjectionType' => 'KEYS_ONLY'],
                'ProvisionedThroughput' => $this->getDefaultProvisionedThroughput(),
            ];

            if ($gsi->getRangeKeyName()) {
                $indexes[$indexName]['KeySchema'][] = ['AttributeName' => $gsi->getRangeKeyName(), 'KeyType' => 'RANGE'];
            }
        }

        $attributes[self::HASH_KEY_NAME] = ['AttributeName' => self::HASH_KEY_NAME, 'AttributeType' => 'S'];
        $attributes = array_values($attributes);
        $indexes = array_values($indexes);

        try {
            $client->createTable([
                'TableName'              => $tableName,
                'AttributeDefinitions'   => $attributes,
                'KeySchema'              => [
                    ['AttributeName' => self::HASH_KEY_NAME, 'KeyType' => 'HASH'],
                ],
                'GlobalSecondaryIndexes' => $indexes,
                'StreamSpecification'    => [
                    'StreamEnabled'  => true,
                    'StreamViewType' => 'NEW_AND_OLD_IMAGES',
                ],
                'ProvisionedThroughput'  => $this->getDefaultProvisionedThroughput(),
            ]);

            $client->waitUntil('TableExists', ['TableName' => $tableName]);
        } catch (\Throwable $e) {
            throw new RepositoryOperationFailed(
                sprintf(
                    '%s::Unable to create table [%s] in region [%s].',
                    ClassUtils::getShortName($this),
                    $tableName,
                    $client->getRegion()
                ),
                Code::INTERNAL,
                $e
            );
        }
    }