{"id":24453,"date":"2023-10-02T05:00:00","date_gmt":"2023-10-02T03:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=24453"},"modified":"2024-07-22T14:30:37","modified_gmt":"2024-07-22T12:30:37","slug":"amazon-qldb-database-similar-to-blockchain","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/amazon-qldb-database-similar-to-blockchain\/","title":{"rendered":"Amazon QLDB \u2013 database similar to blockchain"},"content":{"rendered":"\n<p>Amazon Quantum Ledger Database (Amazon QLDB) is a NoSQL database that aims to provide the following features:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>transparency,<\/li>\n\n\n\n<li>immutability,<\/li>\n\n\n\n<li>cryptographically verifiable transaction log.<\/li>\n<\/ul>\n\n\n\n<p>It allows data to be stored in a secure way that guarantees it cannot be tampered with, as all changes to the database are easily traceable and these traces cannot be removed. This makes <strong>QLDB the perfect database when audit trails are required.<\/strong><\/p>\n\n\n\n<p>The database, called a ledger in QLDB, stores documents that are the counterparts of table rows from relational databases. A full history is available for each of the documents so that any changes made to them can be easily traced. The data can be queried and manipulated using SQL-like language, making it easier to understand how to use QLDB if you come from the world of SQL databases.<\/p>\n\n\n\n<p>In the article you will find information about the journal and its structure, querying and modifying data, examples, legal compliance and the pros and cons of this solution.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Journal<\/strong><\/h2>\n\n\n\n<p>A key component of QLDB is a journal, which is structurally similar to a transaction log in a traditional SQL database, in that all data changes to the database are written to the journal first, in sequential order. However, the journal is append-only, meaning that data can only be inserted into the journal and cannot be deleted or modified. Therefore, <strong>the journal guarantees the transparency of the database<\/strong> and is one of the key features leading to the immutability of the database.<\/p>\n\n\n\n<p>The journal is the source of truth in the database. All the data that users get from it comes from this component, and all data changes are recorded there before they are available to users. It also handles concurrency and guarantees the correct (sequential) order of data changes.<\/p>\n\n\n\n<p>It is possible to retrieve data directly from the journal so that it can be exported if required. Another feature provided by QLDB is <strong>QLDB Stream<\/strong>, which can deliver the data to Kinesis Data Streams for processing in various ways, such as triggering Lambda functions. This results in near real-time processing of data changes introduced in QLDB.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Structure of the journal<\/strong><\/h2>\n\n\n\n<p>QLDB&#8217;s journal is supported by cryptography. Its structure is very similar to that of blockchains. It consists of sequential blocks that are linked together as a chain. Each block consists of user data (actual content), metadata and queries executed in the transaction that committed the block.<\/p>\n\n\n\n<p>The journal block is hashed using the SHA-256 cryptographic function, and its hash is used to calculate the hash of the next block. In this way, if one of the committed blocks is modified, its hash becomes incorrect and the hashes of the next blocks become incorrect as well. So, the verification of the whole chain will eventually fail. This is how the database provides the cryptographically verifiable transaction log.<\/p>\n\n\n\n<p>The structure of the journal is illustrated in the following diagram.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/09\/Obraz1-2.png\"><img decoding=\"async\" width=\"664\" height=\"237\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/09\/Obraz1-2.png\" alt=\"The structure of the journal in Amazon QLDB\" class=\"wp-image-24454\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/09\/Obraz1-2.png 664w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/09\/Obraz1-2-300x107.png 300w\" sizes=\"(max-width: 664px) 100vw, 664px\" \/><\/a><figcaption class=\"wp-element-caption\">Fig. 1 The structure of the journal in Amazon QLDB<\/figcaption><\/figure>\n\n\n\n<p>Each block stores many hashes. The most important are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>block\u2019s hash which uniquely identifies the block \u2013 calculated as the hash of the concatenation of the previous block\u2019s hash and the other hashes in the block (such as hashes of queries and documents),<\/li>\n\n\n\n<li>previous block\u2019s hash \u2013 the \u201cBlock\u2019s hash\u201d value of the previous block. This is how the block is linked to the previous block.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Querying and modifying data<\/strong><\/h2>\n\n\n\n<p>Each time new data is written to the journal, it is materialised into a table, the name of which is specified by the user when inserting the data, just as in a normal SQL INSERT query. The materialised table provides views that allow easy retrieval of the current state of the data as well as the history of the data.<\/p>\n\n\n\n<p>Data can be retrieved from the tables and views using a special SQL-like language called <strong>PartiQL<\/strong>, which is maintained by Amazon. This language can also be used to insert, update and delete data. Note that <strong>any queries that modify the data in any way do not directly modify the data in the tables<\/strong>. Instead, they are appended to the journal as new events, as described in the Journal section.<\/p>\n\n\n\n<p>Each change to the same document results in the creation of a new document revision. Document revisions can be used to check the history of the document.<\/p>\n\n\n\n<p>The data returned by PartiQL from QLDB is in a JSON-like format, which is actually an extension of JSON. The format is called Amazon Ion.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Example<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Create tables<\/strong><\/h3>\n\n\n\n<p>First, we can create tables using PartiQL like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCREATE TABLE BankAccount;\nCREATE TABLE Customer;\n<\/pre><\/div>\n\n\n<p>There is no need to provide any kind of schema because QLDB does not enforce any schema, just like many other NoSQL databases.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Create indexes<\/strong><\/h3>\n\n\n\n<p>We can also add some indexes to the created tables that will improve the performance of querying the data from them.Indexes are used whenever a table is queried to find a document in it using <em>WHERE <\/em>operator with an <em>equality <\/em>operator on an indexed field. If data is queried without using an index, a full table scan is performed, which significantly <strong>reduces performance and increases the cost of the operation<\/strong>. <\/p>\n\n\n\n<p>There is one default index for each table \u2013 the document\u2019s ID, which is automatically generated for each document and is available in the document\u2019s metadata. The indexes can be added like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nCREATE INDEX ON BankAccount (AccountNumber);\nCREATE INDEX ON Customer (IdentityNumber);\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><strong>Insert sample data<\/strong><\/h3>\n\n\n\n<p>We can insert some data into the tables this way:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nINSERT INTO BankAccount\n&amp;lt;&amp;lt; {\n  &#039;AccountNumber&#039;: &#039;123456789&#039;,\n  &#039;AccountType&#039;: &#039;Saving&#039;,\n  &#039;Customer&#039;: { &#039;IdentityNumber&#039;: &#039;Customer1&#039; }\n},\n{\n  &#039;AccountNumber&#039;: &#039;456789123&#039;,\n  &#039;AccountType&#039;: &#039;Checking&#039;,\n  &#039;Customer&#039;: { &#039;IdentityNumber&#039;: &#039;Customer2&#039; }\n} &gt;&gt;;\n\nINSERT INTO Customer\n&amp;lt;&amp;lt; {\n  &#039;IdentityNumber&#039;: &#039;Customer1&#039;,\n  &#039;Name&#039;: &#039;John&#039;,\n  &#039;Surname&#039;: &#039;Doe&#039;\n},\n{\n  &#039;IdentityNumber&#039;: &#039;Customer2&#039;,\n  &#039;Name&#039;: &#039;Doris&#039;,\n  &#039;Surname&#039;: &#039;Lin&#039;\n} &gt;&gt;;\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><strong>Query data<\/strong><\/h3>\n\n\n\n<p>Basically, we can retrieve data just like in SQL databases \u2013 using <em>SELECT <\/em>operator, e.g.:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSELECT * FROM Customer AS c\nWHERE c.Name = &#039;John&#039;;\n<\/pre><\/div>\n\n\n<p>This query returns details of the customer with the name <em>John<\/em>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;\n  {\n    &quot;IdentityNumber&quot;: &quot;Customer1&quot;,\n    &quot;Name&quot;: &quot;John&quot;,\n    &quot;Surname&quot;: &quot;Doe&quot;\n  }\n]\n<\/pre><\/div>\n\n\n<p>We can also join data from two tables like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSELECT c.Name, c.Surname, b.AccountNumber\nFROM Customer AS c, BankAccount as b\nWHERE c.IdentityNumber = b.Customer.IdentityNumber;\n<\/pre><\/div>\n\n\n<p>This query returns customer names along with their account numbers:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;\n  {\n    &quot;Name&quot;: &quot;John&quot;,\n    &quot;Surname&quot;: &quot;Doe&quot;\n    &quot;AccountNumber&quot;: &quot;123456789&quot;\n  },\n  {\n    &quot;Name&quot;: &quot;Doris&quot;,\n    &quot;Surname&quot;: &quot;Lin&quot;\n    &quot;AccountNumber&quot;: &quot;456789123&quot;\n  }\n]\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><strong>Modify data<\/strong><\/h3>\n\n\n\n<p>We can update data like in SQL databases \u2013 using <em>UPDATE <\/em>operator, e.g.:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nUPDATE BankAccount AS b\nSET b.AccountType = &#039;SavingAccount&#039;\nWHERE b.AccountType = &#039;Saving&#039;;\n<\/pre><\/div>\n\n\n<p>Returned data looks like this:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;\n  {\n    &quot;documentId&quot;: &quot;84MQvUwiL6I3QvjowvCW6x&quot;\n  }\n]\n<\/pre><\/div>\n\n\n<p>which is an array with IDs of the new document versions (updated ones).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>View block\u2019s metadata \u2013 committed view<\/strong><\/h3>\n\n\n\n<p>We can query the committed view of the table to get more table details. The view returns documents from the system-defined table directly corresponding to the queried user table. Thus, the view consists of a list of documents from the user table in an extended version consisting of the following attributes:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the current data in the table \u2013 the same as returned by the regular <em>SELECT <\/em>on the table presented above,<\/li>\n\n\n\n<li>the block\u2019s address,<\/li>\n\n\n\n<li>the block\u2019s hash,<\/li>\n\n\n\n<li>the block\u2019s metadata describing the document and the transaction that committed the block.<\/li>\n<\/ul>\n\n\n\n<p>Such queries are typically run to retrieve metadata of documents, in particular system-generated identifiers of the latest revisions of documents stored in a user table or the time at which they were stored (the transaction\u2019s time). Querying a committed view of a table is as simple as modifying the regular <em>SELECT <\/em>query on the table by adding the <em>_ql_committed_ <\/em>prefix to the table name, e.g.:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSELECT * FROM _ql_committed_BankAccount;\n<\/pre><\/div>\n\n\n<p>In general, the <em>_ql_ <\/em>prefix is reserved for system objects in QLDB and committed views are an example of such objects.<\/p>\n\n\n\n<p>The query returns a response that is an array of two elements, because there are two different documents in the <em>BankAccount <\/em>table:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;\n  {\n    blockAddress: {\n      strandId: &quot;IXlQaOgH5XSBHHptx1Anyl&quot;,\n      sequenceNo: 83\n    },\n    hash: {{LZEMR8w8dgk\/XIC\/U1VDR5C3b\/P2YBnwSvqlSOn4GVg=}},\n    data: {\n      AccountNumber: &quot;123456789&quot;,\n      Customer: {\n        IdentityNumber: &quot;Customer1&quot;\n      },\n      AccountType: &quot;SavingAccount&quot;\n    },\n    metadata: {\n      id: &quot;84MQvUwiL6I3QvjowvCW6x&quot;,\n      version: 1,\n      txTime: 2023-08-29T23:05:23.544Z,\n      txId: &quot;42BHOyJI6wQCZ6orjQ0y4H&quot;\n    }\n  },\n  {\n    blockAddress: {\n      strandId: &quot;IXlQaOgH5XSBHHptx1Anyl&quot;,\n      sequenceNo: 31\n    },\n    hash: {{UG+YfHl3hwZofthfoPbWvG5c7k4agKjqtQr3rFYt0z8=}},\n    data: {\n      AccountNumber: &quot;456789123&quot;,\n      AccountType: &quot;Checking&quot;,\n      Customer: {\n        IdentityNumber: &quot;Customer2&quot;\n      }\n    },\n    metadata: {\n      id: &quot;BvtXPJzyhL0DNT262S6hVk&quot;,\n      version: 0,\n      txTime: 2023-08-29T22:47:34.673Z,\n      txId: &quot;72U8fHKd0YU4NI9l8Bg9ae&quot;\n    }\n  }\n]\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\"><strong>View data history<\/strong><\/h3>\n\n\n\n<p>We can also retrieve the data history for a document using the history function, which returns a view containing a list of document revisions with all block details, similar to the use of the <em>_qldb_committed_ <\/em>prefix usage, e.g.:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nSELECT * FROM history(BankAccount)\n<\/pre><\/div>\n\n\n<p>The returned data this time consists of three elements \u2013 two documents originally inserted into the <em>BankAccount <\/em>table and an updated version of one of the documents:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n&#x5B;\n  {\n    blockAddress: {\n      strandId: &quot;IXlQaOgH5XSBHHptx1Anyl&quot;,\n      sequenceNo: 31\n    },\n    hash: {{15G1wu8Pb3RWWOEsmPgEMP51qL89dC1q6PfxnV7q0+o=}},\n    data: {\n      AccountNumber: &quot;123456789&quot;,\n      AccountType: &quot;Saving&quot;,\n      Customer: {\n        IdentityNumber: &quot;Customer1&quot;\n      }\n    },\n    metadata: {\n      id: &quot;84MQvUwiL6I3QvjowvCW6x&quot;,\n      version: 0,\n      txTime: 2023-08-29T22:47:34.673Z,\n      txId: &quot;72U8fHKd0YU4NI9l8Bg9ae&quot;\n    }\n  },\n  {\n    blockAddress: {\n      strandId: &quot;IXlQaOgH5XSBHHptx1Anyl&quot;,\n      sequenceNo: 83\n    },\n    hash: {{LZEMR8w8dgk\/XIC\/U1VDR5C3b\/P2YBnwSvqlSOn4GVg=}},\n    data: {\n      AccountNumber: &quot;123456789&quot;,\n      Customer: {\n        IdentityNumber: &quot;Customer1&quot;\n      },\n      AccountType: &quot;SavingAccount&quot;\n    },\n    metadata: {\n      id: &quot;84MQvUwiL6I3QvjowvCW6x&quot;,\n      version: 1,\n      txTime: 2023-08-29T23:05:23.544Z,\n      txId: &quot;42BHOyJI6wQCZ6orjQ0y4H&quot;\n    }\n  },\n  {\n    blockAddress: {\n      strandId: &quot;IXlQaOgH5XSBHHptx1Anyl&quot;,\n      sequenceNo: 31\n    },\n    hash: {{UG+YfHl3hwZofthfoPbWvG5c7k4agKjqtQr3rFYt0z8=}},\n    data: {\n      AccountNumber: &quot;456789123&quot;,\n      AccountType: &quot;Checking&quot;,\n      Customer: {\n        IdentityNumber: &quot;Customer2&quot;\n      }\n    },\n    metadata: {\n      id: &quot;BvtXPJzyhL0DNT262S6hVk&quot;,\n      version: 0,\n      txTime: 2023-08-29T22:47:34.673Z,\n      txId: &quot;72U8fHKd0YU4NI9l8Bg9ae&quot;\n    }\n  }\n]\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\"><strong>Legal compliance<\/strong><\/h2>\n\n\n\n<p>Some data protection laws, such as the GDPR (General Data Protection Regulation) in the European Union, impose some restrictions and obligations on consumer rights, such as the right to be forgotten in the GDPR. <strong>The immutability of QLDB means that there is no way to comply with such a law, which effectively excludes this database from being used for such data<\/strong>. This significantly limits its usability.<\/p>\n\n\n\n<p>To address this issue, <strong>an exception to the immutability rule has been added to QLDB \u2013 the <em>data redaction<\/em> operation<\/strong>. This operation permanently deletes an inactive document from the QLDB, making it possible to permanently delete some user data. However, it only removes the actual content (data provided by the user), leaving the block itself undeleted. So the block&#8217;s hash, sequence and metadata cannot be deleted and this type of data is stored permanently. In this way, it is possible to combine as much immutability as possible with legal compliance.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Usage analysis<\/strong><\/h2>\n\n\n\n<p>Like any solution, QLDB has advantages and disadvantages. Among them are worth mentioning:<\/p>\n\n\n\n<p><strong>Benefits<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>immutability provides a secure way to store and track data and its changes,<\/li>\n\n\n\n<li>fully auditable data integrity,<\/li>\n\n\n\n<li>2-3 times faster than traditional blockchain frameworks due to the centralised nature of QLDB, as opposed to the decentralised nature of traditional blockchain, which eliminates the need for multi-party consensus.<\/li>\n<\/ul>\n\n\n\n<p><strong>Disadvantages<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>an overhead due to the need to store all data changes in a journal and materialise them in tables, resulting in additional storage and time required to perform operations compared to simpler databases,<\/li>\n\n\n\n<li>a relatively new solution compared to many other databases, so the functionality is still limited, although it has already been significantly extended compared to earlier versions of QLDB.<\/li>\n<\/ul>\n\n\n\n<p>In general, <strong>it may be a good idea to use QLDB where audit trailing is required and the ability to verify data integrity is a must<\/strong>. For less important data, where the extra layer of protection is not a priority, it may be better to use other databases that do not have the overhead of the extra protection.<\/p>\n\n\n\n<p><strong>Examples of use cases where QLDB can be applied:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>financial transaction records,<\/li>\n\n\n\n<li>transaction history in supply chain systems,<\/li>\n\n\n\n<li>claims transaction history in insurance systems,<\/li>\n\n\n\n<li>HR systems maintaining employee data.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>More information<\/strong><\/h2>\n\n\n\n<p>This article is only an overview and contains the most important information about QLDB. However, there are many more details and information that can be found in <a href=\"https:\/\/docs.aws.amazon.com\/qldb\/latest\/developerguide\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >the QLDB Developer Guide<\/a>.<\/p>\n\n\n\n<p>Other knowledge sources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.aws.amazon.com\/qldb\/latest\/developerguide\/what-is.relational-ledger.html\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >A comparison of QLDB and relational databases<\/a> to help those who are more familiar with relational databases understand QLDB concept.<\/li>\n\n\n\n<li><a href=\"https:\/\/docs.aws.amazon.com\/qldb\/latest\/developerguide\/journal-contents.html\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >The exact structure of the journal and its blocks<\/a>, with a detailed example.<\/li>\n\n\n\n<li>More details on the <a href=\"https:\/\/docs.aws.amazon.com\/qldb\/latest\/developerguide\/verification.html\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >topic of QLDB verification process and the security provided by the cryptography<\/a> in QLDB. \u00a0<\/li>\n<\/ul>\n\n\n\n<p>***<\/p>\n\n\n\n<p>If you are interested in the subject of data warehouse, check out this article: &#8220;<a href=\"https:\/\/sii.pl\/blog\/en\/implementation-of-the-modern-data-warehouse-architecture-in-the-azure-cloud\/?category=soft-development&amp;tag=bi-en,data-lake-2,modern-data-warehouse\" target=\"_blank\" aria-label=\"Implementation of the Modern Data Warehouse architecture in the Azure cloud (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\">Implementation of the Modern Data Warehouse architecture in the Azure cloud<\/a>&#8220;. <\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;24453&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;3&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 3)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Amazon QLDB \u2013 database similar to blockchain&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 3)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Amazon Quantum Ledger Database (Amazon QLDB) is a NoSQL database that aims to provide the following features: It allows data &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/amazon-qldb-database-similar-to-blockchain\/\">Continued<\/a><\/p>\n","protected":false},"author":565,"featured_media":24463,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1320],"tags":[2622,1804,1803,1802,1604],"class_list":["post-24453","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-digital-en","tag-blockchain-2","tag-amazon-qldb","tag-database","tag-pros-and-cons"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2023\/09\/Amazon-QLDB-\u2013-database-similar-to-blockchain.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/24453"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/565"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=24453"}],"version-history":[{"count":3,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/24453\/revisions"}],"predecessor-version":[{"id":24462,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/24453\/revisions\/24462"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/24463"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=24453"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=24453"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=24453"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}