<?xml version="1.0"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Datomic Blog</title>
    <link>http://datomic.com</link>
    <atom:link href="http://datomic.com/feed.xml" rel="self" type="application/rss+xml" />
    <description>News from the Datomic team</description>
    <language>en-gb</language>
    <pubDate>Tue, 14 Apr 2026 18:15:45 +0200</pubDate>
    <lastBuildDate>Tue, 14 Apr 2026 18:15:45 +0200</lastBuildDate>

    <item>
      <title>Datomic at Clojure/Conj 2025</title>
      <link>https://blog.datomic.com/2026/01/conj2025.html</link>
      <pubDate>Wed, 21 Jan 2026 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2026/01/conj2025.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>Happy belated new year! The Datomic team was among the six hundred participants at <a href="https://www.2025.clojure-conj.org/">Clojure/Conj 2025</a>. Here are some highlights.</p>
</div>
<div class="sect3">
<h4 id="_lessons_from_production">Lessons from Production</h4>
<div class="paragraph">
<p><a href="https://www.youtube.com/watch?v=gJ9UZlr6C6M">A Decade on Datomic</a> was full of lessons from Davis Shepherd and Jonathan Indig’s experience at Netflix. This is a technical talk with plenty of detail on how to leverage the semantics of a <a href="https://www.youtube.com/watch?v=Cym4TZwTCNU">"deconstructed" database</a> to design solutions for distributed systems challenges. We’ve put together a <a href="https://github.com/daveliepmann/talk-transcripts/blob/master/Shepherd_Davis_and_Indig_Jonathan_(Netflix)/ADecadeOnDatomic.md">transcript</a> for those who prefer a written version.</p>
</div>
<div class="paragraph">
<p>Tim Pote took us onto the warehouse floor in <a href="https://www.youtube.com/watch?v=NV02r1Y1B-8">Forklifts, Facts, and Functions</a> (<a href="https://github.com/daveliepmann/talk-transcripts/blob/master/Pote_Tim/ForkliftsFactsAndFunctions.md">transcript</a>). He illustrated how Datomic’s flexible schema and queryable history gave him the leverage to solve bugs simply and easily.</p>
</div>
<div class="paragraph">
<p>Darlei Soares and João Nascimento showed how they used Datomic to model Nubank microservices in <a href="https://www.youtube.com/watch?v=1vBm9XvS5QI">Immutable Knowledge Databases</a> (<a href="https://github.com/daveliepmann/talk-transcripts/blob/master/Soares_Darlei_and_Nascimento_Jo%C3%A3o/ImmutableKnowledgeDatabases.md">transcript</a>), revealing dependency patterns, risks and opportunities.</p>
</div>
</div>
<div class="sect3">
<h4 id="_amazing_day_of_datomic">Amazing Day of Datomic</h4>
<div class="paragraph">
<p>Our hands-on workshop is back. Based on Stuart Halloway’s original <a href="https://docs.datomic.com/resources/day-of-datomic.html">Day of Datomic</a>, the event was led by Nubank engineers Hanna Figueiredo and Carol Silva.</p>
</div>
<div class="paragraph">
<p>Our priority for the session was to incorporate the latest features and architectural insights. Feedback was overwhelmingly positive, with 100% of participants reporting improved mastery, specifically praising the combination of architectural “deep dives” and practical challenges. We appreciate everyone who took part and made it so interactive. The workshop remains one of our favorite ways to help developers gain a solid base of understanding Datomic’s unique power.</p>
</div>
</div>
<div class="sect3">
<h4 id="_fresh_datomic_tools">Fresh Datomic Tools</h4>
<div class="paragraph">
<p>Dustin Getz’s tour of <a href="https://www.youtube.com/watch?v=dmucZkE5gd0">A Datomic entity browser for prod</a> (<a href="https://github.com/daveliepmann/talk-transcripts/blob/master/Getz_Dustin/ADatomicEntityBrowserForProd.md">transcript</a>) was electrifying. The tool is part programmable spreadsheet and part visual graph explorer, with features like query monitoring and a powerful query DSL to make a smooth developer experience. We’re eager to see where this power will be applied.</p>
</div>
</div>
<div class="sect3">
<h4 id="_datomic_in_computational_biology">Datomic in Computational biology</h4>
<div class="paragraph">
<p>Benjamin Kamphaus’s <a href="https://www.youtube.com/watch?v=HU-uwSUZETw">Power Tools for Translational Data Science</a> (<a href="https://github.com/daveliepmann/talk-transcripts/blob/master/Kamphaus_Ben/UnifyBioPowerToolsForTranslationalDataScience.md">transcript</a>) was a more philosophical talk. It weaves historical linguistics, computational phylogenetics, constraint satisfaction, and the biology of rare cancers into a parable on why it matters how we build our tools.</p>
</div>
<div class="paragraph">
<p>It builds on his prior talks about his data science toolkit, <a href="https://www.youtube.com/watch?v=ulhr_50bevk">Clojure Where it Counts: Tidying Data Science Workflows</a> (with Pier Federico) and <a href="https://www.youtube.com/watch?v=vwZxHVcfwuw">Building a Unified Cancer Immunotherapy Data Library</a> (with Lacey Kitch), both of which dive more into the technical advantages that Clojure and Datomic provide.</p>
</div>
<div class="imageblock">
<div class="content">
<img src="datomic-at-conj2025.jpg" alt="Some Datomic team members at Conj">
</div>
</div>
<div class="paragraph">
<p>Thanks to the organizers, speakers, and everyone who made the Conj such a vibrant time. We hope to see you there next year!</p>
</div>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Amazing Day of Datomic</title>
      <link>https://blog.datomic.com/2024/09/Amazing-Day-of-Datomic.html</link>
      <pubDate>Fri, 13 Sep 2024 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2024/09/Amazing-Day-of-Datomic.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>The Amazing Day of Datomic!</p>
</div>
<div class="paragraph">
<p>Join us for The Amazing Day of Datomic on Wed Oct 23, 1-5 pm at <a href="https://2024.clojure-conj.org">Clojure Conj 2024</a>. Amazing Day of Datomic is a comprehensive training program inspired by Stuart Halloway’s original “<a href="https://docs.datomic.com/resources/day-of-datomic.html">Day of Datomic</a>.” This updated version includes new features and insights, designed to provide you with a solid grasp of Datomic, from basic concepts to intermediate knowledge.</p>
</div>
<div class="ulist">
<div class="title">What You’ll Learn:</div>
<ul>
<li>
<p>Fundamentals Overview</p>
</li>
<li>
<p>Effective use of Datomic</p>
</li>
<li>
<p>Understanding Datomic operations</p>
</li>
<li>
<p>Troubleshooting techniques</p>
</li>
<li>
<p>And much more!</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Don’t miss this opportunity to enhance your skills and knowledge with the latest updates in Datomic. <a href="https://ti.to/nubank/clojureconj-2024">Sign up today</a>.</p>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Jepsen Tests Datomic</title>
      <link>https://blog.datomic.com/2024/05/Jepsen-tests-Datomic.html</link>
      <pubDate>Wed, 15 May 2024 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2024/05/Jepsen-tests-Datomic.html</guid>
      	<description>
        <![CDATA[
	<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p><a href="https://docs.datomic.com/datomic-overview.html">Datomic</a> is a general purpose database system designed for data-of-record applications. A Datomic database is a set of immutable atomic facts called <a href="https://docs.datomic.com/glossary.html#datom">datoms</a>. Datomic transactions add datoms, never updating or removing them, so you have a complete audit trail for data and the ability to query “as of” points in time. Datomic transactions are serialized in a total order, providing strong ACID guarantees.</p>
</div>
<div class="paragraph">
<p>Datomic has a powerful and flexible information model. Each Datomic database declares an attribute-level schema, and any entity can possess any attribute. You can query your data with datalog (a logic-based query) and navigate arbitrary hierarchies with pull. Datomic’s indexes automatically support many access patterns common in SQL, column, K/V, hierarchical, and graph databases.</p>
</div>
<div class="paragraph">
<p>Datomic is developed by Nubank, one of the world’s largest digital financial services platforms, serving over 100 million customers across Brazil, Mexico, and Colombia. At Nubank we use Datomic for almost all of our suite of products resulting in an average of 2.5 billion Datomic transactions being processed each day!</p>
</div>
</div>
</div>
<h1 id="_what_is_jepsen" class="sect0">What is Jepsen?</h1>
<div class="paragraph">
<p><a href="https://jepsen.io/">Jepsen</a> is a small consultancy focused on distributed systems safety. They write public reports, maintain open-source tooling, and offer training courses to make databases, queues, and other systems safer. Jepsen works with vendors like Nubank to evaluate their documentation and system behavior under a variety of failure modes, helps those vendors identify and fix bugs and documentation errors, and writes an analysis presenting their findings and recommendations for both vendors and users.</p>
</div>
<h1 id="_jepsen_analysis_outcome" class="sect0">Jepsen Analysis Outcome</h1>
<div class="paragraph">
<p>Today, Jepsen released their analysis of Datomic’s <a href="https://jepsen.io/analyses/datomic-pro-1.0.7075">safety and correctness</a>.</p>
</div>
<div class="paragraph">
<p>Datomic aced the inter-transaction test and then some. Jepsen concluded:</p>
</div>
<div class="quoteblock">
<blockquote>
<div class="paragraph">
<p>We found no behavior which violated Datomic’s core safety claims. Transactions appeared to execute as if they had been applied in
a total order, and that order was consistent with the local order of operations on each peer. Histories restricted to just those
transactions performing writes, and histories in which reads used <code>(d/sync conn)</code> to obtain a current copy of the database, were
consistent with real-time order.</p>
</div>
<div class="paragraph">
<p>…</p>
</div>
<div class="paragraph">
<p>Indeed, we believe Datomic’s inter-transaction safety properties are stronger than promised.</p>
</div>
</blockquote>
</div>
<div class="paragraph">
<p>Based on these findings, we decided to <a href="https://docs.datomic.com/transactions/acid.html">strengthen and clarify our documentation about ACID properties</a>.</p>
</div>
<div class="paragraph">
<p>Jepsen’s intra-transaction tests also confirmed Datomic’s semantics. These tests required a great deal of explanation in the report. Most databases and formalisms for serializability provide sequential execution semantics within a transaction. Datomic applies most elements of a transaction in a semantically parallel manner. As a result, we updated our docs to better explain <a href="https://docs.datomic.com/transactions/transactions.html">Datomic’s transactions</a>, <a href="https://docs.datomic.com/tech-notes/composing-transactions-by-example.html">how they are composed</a>, and <a href="https://docs.datomic.com/tech-notes/comparison-with-updating-transactions.html">how they compare to other systems</a>.</p>
</div>
<div class="paragraph">
<p>Jepsen now tests Datomic in our CI system!</p>
</div>
<h1 id="_conclusion" class="sect0">Conclusion</h1>
<div class="paragraph">
<p>Our partnership with Jepsen validated that Datomic is safe under a wide variety of circumstances, motivated valuable documentation improvements, and introduced a new battery of correctness tests that is now being used in our CI suite to continually ensure Datomic maintains the same high level of safety as the product evolves.</p>
</div>
<div class="paragraph">
<p>Our <a href="https://building.nubank.com.br">Building Nubank</a> blog has more content like this, dedicated to cutting-edge technologies!</p>
</div>
<div class="paragraph">
<p>Please check out <a href="https://international.nubank.com.br/careers/">Careers at Nu</a> if you are interested in joining our team!</p>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Local is Released</title>
      <link>https://blog.datomic.com/2023/08/datomic-local-is-released.html</link>
      <pubDate>Wed, 16 Aug 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/08/datomic-local-is-released.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>The Datomic team is excited to announce the launch of <a href="https://docs.datomic.com/cloud/datomic-local.html">Datomic Local</a> under the <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache License 2.0</a>. Datomic Local is a library that is both embeddable and redistributable. It is a lightweight version of Datomic, designed to be easily embedded within applications and freely redistributed. Datomic Local supports the Client API, making it an excellent choice for small single-process applications and for testing systems that are based on the Datomic Client API.</p>
</div>
<div class="sect2">
<h3 id="_what_is_new">What is new?</h3>
<div class="paragraph">
<p>Datomic Local is a lightweight version of Datomic backed by local storage that supports the <a href="https://docs.datomic.com/cloud/client/client-api.html">Client API</a>. The Datomic Local and supporting binaries are released under the <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache License 2.0</a> license.</p>
</div>
</div>
<div class="sect2">
<h3 id="_how_to_get_it">How to get it</h3>
<div class="paragraph">
<p>Datomic Local is available on <a href="https://central.sonatype.com/artifact/com.datomic/local/1.0.267">Maven Central</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_use_cases">Use cases</h3>
<div class="paragraph">
<p>The Datomic Local version of Datomic is indicated for:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>People who want to write libraries that depend on Datomic</p>
</li>
<li>
<p>People who want an embedded DB</p>
</li>
<li>
<p>Cloud users who want to dev locally</p>
</li>
<li>
<p>People who already use dev-local</p>
</li>
</ul>
</div>
</div>
<h1 id="_faq" class="sect0">FAQ</h1>
<div class="sect2">
<h3 id="_what_is_datomic_local">What is Datomic Local?</h3>
<div class="paragraph">
<p>Datomic Local is a lightweight version of Datomic backed by local storage which supports the Client API.</p>
</div>
</div>
<div class="sect2">
<h3 id="_what_changed">What changed?</h3>
<div class="paragraph">
<p>Datomic Local is a library, embeddable, and redistributable. Datomic Local replaces dev-local.</p>
</div>
</div>
<div class="sect2">
<h3 id="_how_to_get_datomic_local">How to get Datomic Local?</h3>
<div class="paragraph">
<p>Datomic Local is available on <a href="https://central.sonatype.com/artifact/com.datomic/local/1.0.267">Maven Central</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_what_changes_in_terms_of_licensing">What changes in terms of licensing?</h3>
<div class="paragraph">
<p>The Datomic Local binary is available under the <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0 License</a>, which means that it is possible to redistribute it.</p>
</div>
</div>
<div class="sect2">
<h3 id="_for_whom_is_datomic_local_recommended">For whom is Datomic Local recommended?</h3>
<div class="ulist">
<ul>
<li>
<p>People who want to write libraries that depend on Datomic</p>
</li>
<li>
<p>People who want an embedded DB</p>
</li>
<li>
<p>Cloud users who want to dev locally</p>
</li>
<li>
<p>People who already use dev-local</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_what_happened_to_datomic_free">What happened to Datomic Free?</h3>
<div class="paragraph">
<p>If you are used to using Datomic Free, use <a href="https://www.datomic.com/">Datomic Pro</a>. If you want a redistributable, embeddable Datomic, use Datomic Local.</p>
</div>
</div>
<div class="sect2">
<h3 id="_what_is_the_difference_between_datomic_cloud_datomic_local_and_datomic_pro">What is the difference between Datomic Cloud, Datomic Local, and Datomic Pro?</h3>
<div class="paragraph">
<p><a href="https://docs.datomic.com/cloud/index.html"><strong>Datomic Cloud</strong></a> is tightly integrated with AWS. It supports only client access. Datomic Cloud has ions, which allows users to run entire applications on Datomic, with reproducible deployment, elastic autoscaling, and integration via AWS Lambda events and AWS API Gateway.</p>
</div>
<div class="paragraph">
<p><a href="https://docs.datomic.com/pro/overview/introduction.html"><strong>Datomic Pro</strong></a> is a distributed database designed to enable scalable, flexible applications running on-premises or in the cloud. It is fully designed for use against multiple storages in large-scale, multi-user systems.</p>
</div>
<div class="paragraph">
<p><a href="https://docs.datomic.com/cloud/datomic-local.html"><strong>Datomic Local</strong></a> is a lightweight version of Datomic that is embeddable, redistributable, and supports the Client API. It is well suited for single-process applications and for testing Client API-based Datomic systems.</p>
</div>
</div>
<div class="sect2">
<h3 id="_is_datomic_local_open_source">Is Datomic Local open source?</h3>
<div class="paragraph">
<p>No. The <em>binaries</em> are Apache 2.0, as with other versions of Datomic.</p>
</div>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Cloud is Free</title>
      <link>https://blog.datomic.com/2023/06/datomic-cloud-is-free.html</link>
      <pubDate>Fri, 16 Jun 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/06/datomic-cloud-is-free.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>Nubank is excited to announce today that Datomic Cloud is also now available free of licensing fees, and the Datomic binaries are being released under the <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0</a> license.
Starting with this version, <a href="https://docs.datomic.com/cloud">Datomic Cloud</a> is now easier to get. To set up Datomic Cloud, check the instructions on <a href="https://docs.datomic.com/cloud/getting-started/getting-started.html">how to get started</a>.
We aim to make Datomic even more useful to more people in more situations. We are looking forward to expanding Datomic and Clojure worldwide!</p>
</div>
<h1 id="_faq" class="sect0">FAQ</h1>
<div class="sect2">
<h3 id="_whats_changing_for_customers">What&#8217;s changing for customers?</h3>
<div class="paragraph">
<p>Moving forward, we are making the software <a href="https://docs.datomic.com/cloud/releases.html">easily available to everyone</a>, at no cost. As of version <a href="https://docs.datomic.com/cloud/changes.html#995-9204">995-9204</a> there will no longer be licensing fees associated with your use of Datomic Cloud.</p>
</div>
<div class="paragraph">
<p>All current agreements and support are continued in full effect. We will continue to offer paid enterprise support.</p>
</div>
<div class="paragraph">
<p>If you are interested in continuing support, and or leveraging the new licensing <a href="mailto:support@cognitect.com">call us</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_what_if_im_on_an_older_version_of_datomic_cloud">What if I&#8217;m on an older version of Datomic Cloud?</h3>
<div class="paragraph">
<p>Customers on versions of Datomic Cloud earlier than <a href="https://docs.datomic.com/cloud/changes.html#995-9204">995-9204</a> may continue to be charged fees associated with Datomic Cloud until they upgrade.</p>
</div>
</div>
<div class="sect2">
<h3 id="_why_did_you_choose_the_apache_2_0_license">Why did you choose the Apache 2.0 license?</h3>
<div class="paragraph">
<p>We want to make Datomic more useful to more people in more situations. The <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a> provides benefits to Datomic users in the areas of copyright, patent, redistribution, and more&#8201;&#8212;&#8201;just as it does for countless other projects.</p>
</div>
</div>
<div class="sect2">
<h3 id="_is_it_open_source">Is it Open Source?</h3>
<div class="paragraph">
<p>No. Datomic binaries are provided under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2</a> license which grants all the same rights to a work delivered in object form.</p>
</div>
<div class="paragraph">
<p>Datomic will continue to be developed at Nubank, where it is a critical piece of our infrastructure.</p>
</div>
</div>
<div class="sect2">
<h3 id="_will_pro_support_2_day_sla_business_hour_be_provided">Will Pro support (2 day SLA business hour) be provided?</h3>
<div class="paragraph">
<p>Yes, through the duration of your current license term. Moving forward, <a href="https://www.datomic.com/contact.html">contact us</a> if you are interested in an <a href="https://www.datomic.com/get-datomic.html">Enterprise Support</a> agreement.</p>
</div>
</div>
<div class="sect2">
<h3 id="_where_can_i_find_out_more">Where can I find out more?</h3>
<div class="ulist">
<ul>
<li>
<p><a href="http://www.datomic.com">www.datomic.com</a></p>
</li>
<li>
<p><a href="https://docs.datomic.com/cloud/">Datomic Cloud Documentation</a></p>
</li>
<li>
<p><a href="https://ask.datomic.com">ask.datomic</a></p>
</li>
<li>
<p><a href="https://forum.datomic.com">Datomic Forum</a></p>
</li>
<li>
<p><a href="https://clojurians.slack.com/archives/C03RZMDSH">#datomic in Clojurians Slack</a></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_can_i_now_run_datomic_cloud_off_marketplace">Can I now run Datomic Cloud off marketplace?</h3>
<div class="paragraph">
<p>Yes.</p>
</div>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Datomic is Free</title>
      <link>https://blog.datomic.com/2023/04/datomic-is-free.html</link>
      <pubDate>Thu, 27 Apr 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/04/datomic-is-free.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>Nubank is excited to announce today that we are making all editions of Datomic available free of licensing fees. The Datomic binaries are being released under the <a href="https://www.apache.org/licenses/LICENSE-2.0.html">Apache 2.0</a> license and will be readily available for direct download and use via Maven Central - no signup required. <a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf">Datomic Cloud</a> will be available on AWS Marketplace with no additional software cost.</p>
</div>
<div class="paragraph">
<p>We are doing this to make Datomic more useful to more people in more situations, and look forward to expanding the Datomic and Clojure community as a result.</p>
</div>
<h1 id="_faq" class="sect0">FAQ</h1>
<div class="sect2">
<h3 id="_whats_changing_for_customers">What&#8217;s changing for customers?</h3>
<div class="paragraph">
<p>Moving forward, we are making the software <a href="https://docs.datomic.com/pro/releases.html">easily available to everyone</a>, at no cost.</p>
</div>
<div class="paragraph">
<p>All current agreements and support are continued in full effect. We will continue to offer paid enterprise support.</p>
</div>
<div class="paragraph">
<p>If you are interested in continuing support, and or leveraging the new licensing <a href="mailto:support@cognitect.com">call us</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="_which_editions_of_datomic_will_be_free">Which editions of Datomic will be free?</h3>
<div class="paragraph">
<p>All of them. Datomic Pro is free of licensing fees, and now <a href="https://blog.datomic.com/2023/06/datomic-cloud-is-free.html">Datomic Cloud is available off AWS Marketplace with no associated license fees.</a></p>
</div>
</div>
<div class="sect2">
<h3 id="_why_did_you_choose_the_apache_2_0_license">Why did you choose the Apache 2.0 license?</h3>
<div class="paragraph">
<p>We want to make Datomic more useful to more people in more situations. The <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 license</a> provides benefits to Datomic users in the areas of copyright, patent, redistribution, and more&#8201;&#8212;&#8201;just as it does for countless other projects.</p>
</div>
</div>
<div class="sect2">
<h3 id="_is_it_open_source">Is it Open Source?</h3>
<div class="paragraph">
<p>No. Datomic binaries are provided under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2</a> license which grants all the same rights to a work delivered in object form.</p>
</div>
<div class="paragraph">
<p>Datomic will continue to be developed at Nubank, where it is a critical piece of our infrastructure.</p>
</div>
</div>
<div class="sect2">
<h3 id="_will_pro_support_2_day_sla_business_hour_be_provided">Will Pro support (2 day SLA business hour) be provided?</h3>
<div class="paragraph">
<p>Yes, through the duration of your current license term. Moving forward, <a href="https://www.datomic.com/contact.html">contact us</a> if you are interested in an <a href="https://www.datomic.com/get-datomic.html">Enterprise Support</a> agreement.</p>
</div>
</div>
<div class="sect2">
<h3 id="_where_can_i_find_out_more">Where can I find out more?</h3>
<div class="ulist">
<ul>
<li>
<p><a href="http://www.datomic.com">www.datomic.com</a></p>
</li>
<li>
<p><a href="https://docs.datomic.com">Datomic Documentation</a></p>
</li>
<li>
<p><a href="https://ask.datomic.com">ask.datomic</a></p>
</li>
<li>
<p><a href="https://forum.datomic.com">Datomic Forum</a></p>
</li>
<li>
<p><a href="https://clojurians.slack.com/archives/C03RZMDSH">#datomic in Clojurians Slack</a></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_can_i_now_run_datomic_cloud_off_marketplace">Can I now run Datomic Cloud off marketplace?</h3>
<div class="paragraph">
<p>Yes! See our <a href="https://blog.datomic.com/2023/06/datomic-cloud-is-free.html">Datomic Cloud is Free post</a></p>
</div>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Implicit Partitions</title>
      <link>https://blog.datomic.com/2023/04/implicit-partitions.html</link>
      <pubDate>Thu, 20 Apr 2023 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2023/04/implicit-partitions.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>If you have an application that is struggling with performance, it might be due to poor data locality, the physical
distribution of relevant information. A query that is searching for sparsely distributed data will find few results per
storage read. Conversely, queries can efficiently slurp relevant data when it is densely colocated. Datomic&#8217;s partitions
allow applications to group entities together and gain control over locality. Entities that share a partition will
be colocated in the E-leading indexes, EAVT and AEVT. Because each partition requires a name and installation prior
to its use, it can become cumbersome to build schemes that use many partitions.</p>
</div>
<div class="paragraph">
<p>Today&#8217;s release of Datomic On-Prem includes a new feature: <a href="https://docs.datomic.com/on-prem/schema/schema.html#implicit-partitions">Implicit Partitions</a>. These partitions are identified by an
integer, and they are usable without an installation step. There are 524288 (2^19) implicit partitions in each Datomic
database, and these facilitate the use of algorithmic partition assignment strategies, e.g. deterministically assigning
each customer to a particular partition, or assigning time-windowed data to different partitions.</p>
</div>
<div class="paragraph">
<p>Applications can transact entities into implicit partitions by passing one to d/tempid:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="clojure">(d/transact conn [{:db/id (d/tempid (d/implicit-part 55))
                   :movie/title "The Great Gatsby"}])</code></pre>
</div>
</div>
<div class="paragraph">
<p>We are also introducing two new transaction data directives that facilitate partition assignment. To request put a new
entity into a particular partition, you can include its tempid in the :db/force-partition map. This can appear anywhere
in a transaction map form. Here is the same transaction using this directive with a string tempid:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="clojure">(d/transact conn [{:db/id "movie"
                   :movie/title "The Great Gatsby"
                   :db/force-partition {"movie" (d/implicit-part 55)}}])</code></pre>
</div>
</div>
<div class="paragraph">
<p>The :db/match-partition directive says that an entity should have the same partition as another entity. Here, both items
will be in the same partition as its order, which is in implicit partition 15555:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="clojure">(d/transact conn
            [{:db/id    "order"
              :order/id 123
              :order/items ["item1" "item2"]}

             {:db/id     "item1"
              :item/name "cereal"
              :item/sku  "A150"}

             {:db/id     "item2"
              :item/name "milk"
              :item/sku  "T770"}

             {:db/force-partition {"order" (d/implicit-part 15555)}
              :db/match-partition {"item1" "order"
                                   "item2" "order"}}])</code></pre>
</div>
</div>
<div class="paragraph">
<p>To learn more about implicit partitions, read the documentation for <a href="https://docs.datomic.com/on-prem/schema/schema.html#implicit-partitions">Implicit Partitions</a> and <a href="https://docs.datomic.com/on-prem/transactions/transactions.html#partition-assignment">Controlling Partition Assignment</a>, and the API documentation for <a href="https://docs.datomic.com/on-prem/clojure/index.html">Datomic On-Prem</a>.</p>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Query Stats</title>
      <link>https://blog.datomic.com/2023/01/Query-Stats.html</link>
      <pubDate>Wed, 25 Jan 2023 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2023/01/Query-Stats.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>Today&#8217;s release of Datomic On-Prem, and coming soon in Cloud, includes a new feature: query-stats.</p>
</div>
<div class="paragraph">
<p>query-stats is a new feature that gives users visibility into the decisions made by the query engine while it processed your query. Datomic users can leverage the information returned by query-stats to find the optimal clause ordering for a query as well as gain visibility into various query components including query clauses, query rules, and query expressions.</p>
</div>
<div class="paragraph">
<p>For example, given the following query:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="clojure">{:find  [(count ?artist-name)]
 :where [[?release :release/name ?release-name]
         [?release :release/artists ?artist]
         [?artist :artist/name ?artist-name]]}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The following query-stats are returned:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="clojure">{:ret         [[4587]],
 :query-stats {:query  {:find  [(count ?artist-name)],
                        :where [[?release :release/name ?release-name]
                                [?release :release/artists ?artist]
                                [?artist :artist/name ?artist-name]]},
               :phases [{:sched   (([?release :release/name ?release-name]
                                    [?release :release/artists ?artist]
                                    [?artist :artist/name ?artist-name])),
                         :clauses [{:clause [?release :release/name ?release-name], :rows-in 0, :rows-out 11434, :binds-in (), :binds-out [?release], :expansion 11434, :warnings {:unbound-vars #{?release ?release-name}}}
                                   {:clause [?release :release/artists ?artist], :rows-in 11434, :rows-out 4600, :binds-in [?release], :binds-out [?artist]}
                                   {:clause [?artist :artist/name ?artist-name], :rows-in 4600, :rows-out 4587, :binds-in [?artist], :binds-out [?artist-name]}]}]}}</code></pre>
</div>
</div>
<div class="paragraph">
<p>This output can be more easily interpreted using REBL:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="40473ee8-8ba1-480f-92ed-28af07fe858f.png" alt="40473ee8 8ba1 480f 92ed 28af07fe858f">
</div>
</div>
<div class="paragraph">
<p>To learn more about query-stats and other enhancements:</p>
</div>
<div class="paragraph">
<p>Read the release announcement for <a href="https://forum.datomic.com/t/datomic-1-0-6610-now-available/2176">Datomic On-Prem</a>.</p>
</div>
<div class="paragraph">
<p>Read the API documentation for <a href="https://docs.datomic.com/on-prem/api/query-stats.html">Datomic On-Prem</a>.</p>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Cloud 884-9095: New tiers and internet access</title>
      <link>https://blog.datomic.com/2021/07/Datomic-Cloud-884-9095-New-tiers-and-internet-access.html</link>
      <pubDate>Tue, 13 Jul 2021 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2021/07/Datomic-Cloud-884-9095-New-tiers-and-internet-access.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>Datomic Cloud 884-9095 is a major new release offering more instance
options, lower pricing, API Gateway automation for ions and clients,
and more.</p>
</div>
<div class="sect1">
<h2 id="_more_instance_options">More instance options</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Datomic now provides a
<a href="https://docs.datomic.com//whatis/configurations-and-pricing.html">wider variety of compute, memory, and monitoring choices</a>.
Basic compute instances start from t3.small and
step up to t3.2xlarge, letting you ramp up on capability and cost
linearly.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_lower_pricing_at_all_scales">Lower pricing at all scales</h2>
<div class="sectionbody">
<div class="paragraph">
<p>All instances sizes now cost less to run. If you were running Solo before,
you can <a href="https://docs.datomic.com//changes.html#884-solo">now run the smallest production tier</a>,
including a load balancer, for what solo cost before. If you are running production,
your cost <a href="https://docs.datomic.com//changes.html#884-prod">will be lower at your current instance size</a>,
and you may be able to select a smaller instance size as well.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_new_automation_ion_web_applications">New automation ion web applications</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Datomic&#8217;s CloudFormation templates can
<a href="https://docs.datomic.com//operation/architecture.html#api-gateway">automatically setup both the VPC link and API Gateway</a>
needed to expose your web application (ion).</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_new_client_access_from_outside_the_vpc">New client access from outside the VPC</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Building on the new API Gateway automation, you can now elect to
<a href="https://docs.datomic.com//operation/architecture.html#api-gateway">access your Datomic cloud system via an automatically-configured API Gateway</a>,
obviating the need for an access gateway and SOCKS proxy.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_run_and_scale_analytics_anywhere">Run and scale analytics anywhere</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Datomic <a href="https://docs.datomic.com//operation/architecture.html#analytics">analytics support</a>
is now available via a
<a href="https://docs.datomic.com//analytics/analytics-configuring.html">Datomic connector for Trino</a>.
With this connector, you can run analytics anywhere that you
would like, e.g. a dev laptop or a cluster in EC2. You can also access
Trino features including clustering and federation.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_security_first">Security first</h2>
<div class="sectionbody">
<div class="paragraph">
<p>All of the new access points described above (web ions, client access,
and analytics) are
<a href="https://docs.datomic.com//operation/architecture.html#security">secured via TLS, and Datomic compute nodes continue to run in a private VPC</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_metrics_choices">Metrics choices</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Datomic metrics are now available
<a href="https://docs.datomic.com//operation/growing-your-system.html">in two tiers: basic or detailed</a>.
(You can also turn off metrics entirely.) These choices let
you minimize cost or maximize observability, independently for each
compute group.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_try_it">Try it</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If you are an existing Datomic Cloud user, this release significantly
simplifies operations. Before you upgrade, please read <a href="https://docs.datomic.com//changes.html#884-9095">the changelog</a>
carefully, so that you understand all the things you will no longer
need to do.</p>
</div>
<div class="paragraph">
<p>If you are new to Datomic Cloud, <a href="https://docs.datomic.com//getting-started/start-system.html">getting started</a> has never been easier.</p>
</div>
</div>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Knowledgebase</title>
      <link>https://blog.datomic.com/2020/10/datomic-knowledgebase.html</link>
      <pubDate>Thu, 22 Oct 2020 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2020/10/datomic-knowledgebase.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>The <a href="http://ask.datomic.com/">Datomic Knowledgebase</a> has been launched to provide a place to <a href="https://ask.datomic.com/index.php/ask">ask questions, provide answers, discuss and make feature requests</a>.</p>
</div>
<div class="paragraph">
<p>Datomic Knowledgebase represents our commitment to improve <a href="https://docs.datomic.com/on-prem/index.html">Datomic</a> and <a href="https://docs.datomic.com/cloud/index.html">Datomic Cloud</a>.  It will serve as a place where you can help us prioritize our efforts and help shape the future of Datomic.</p>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Cognitect Joins Nubank!</title>
      <link>https://blog.datomic.com/2020/07/cognitect-joins-nubank.html</link>
      <pubDate>Thu, 23 Jul 2020 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2020/07/cognitect-joins-nubank.html</guid>
      	<description>
        <![CDATA[
	<div class="paragraph">
<p>We are thrilled to announce that Cognitect is joining
the Nubank family of companies. This is the next step in a long
relationship, and opens new opportunities for Clojure and Datomic
worldwide. Please read the full story over on the
<a href="https://cognitect.com/blog/2020/07/23/Cognitect-Joins-Nubank">Cognitect Blog</a>.</p>
</div>
  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Analytics (Preview)</title>
      <link>https://blog.datomic.com/2019/10/datomic-analytics-preview.html</link>
      <pubDate>Sun, 1 Sep 2019 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2019/10/datomic-analytics-preview.html</guid>
      	<description>
        <![CDATA[
	<div
    style=" color: #172b4d; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin-top: 10px; padding: 0px; white-space: pre-wrap;">
    Today's releases of <a class="sc-bnXvFD gYgFVI" href="https://docs.datomic.com/cloud/index.html"
        style="color: #0052cc; text-decoration-line: none;" title="https://docs.datomic.com/cloud/index.html"><u>Datomic Cloud</u></a> and <a class="sc-bnXvFD gYgFVI" href="https://docs.datomic.com/on-prem/index.html"
        style="color: #0052cc; text-decoration-line: none;"
        title="https://docs.datomic.com/on-prem/index.html"><u>Datomic On-Prem</u></a> preview a major new feature: analytics support.</div>
<div
    style=" color: #172b4d; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin-top: 10px; padding: 0px; white-space: pre-wrap;">
    With analytics support, your data scientists, analysts, and operations people can directly access Datomic using the languages and tools they already know (e.g. SQL, Python, R, Tableau, Metabase, Superset and more), without you having to do any ETL.</div>
<div
    style=" color: #172b4d; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin-top: 10px; padding: 0px; white-space: pre-wrap;">
    The analytics metaschema specifies a mapping from Datomic entities and attributes to dynamic SQL tables and columns, as shown in the example below:<a href="https://www.youtube.com/watch?v=jVKGYu0_OCA"><img border="0"
            data-original-height="703" data-original-width="1600" src="/images/blog/-Ec0OoaOk1ss/XZNv6C9KuTI/AAAAAAAAAl0/kva0YdqvLQoT9DE1CP-59BiPG4HcS8x0ACLcBGAsYHQ/s1600/analyticsTables.png" /></a>
</div>
<div
    style=" color: #172b4d; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin-top: 10px; padding: 0px; white-space: pre-wrap;">
    <span style="letter-spacing: -0.005em;">In Cloud, the bastion server has been renamed to access gateway, as it now also supports analytics. Analytics support is automatic when you select an EC2 instance size that supports it, and costs nothing beyond the cost of the EC2 instance.</span></div>
<div
    style=" color: #172b4d; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin-top: 10px; padding: 0px; white-space: pre-wrap;">
    <span style="font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif;">In On-Prem, analytics support is available via the </span><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">bin/presto</span><span style="font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif;"> script in the distribution.</span></div>
<div style=" color: #172b4d; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin-top: 10px; padding: 0px; white-space: pre-wrap;"> To learn more about the analytics preview:</div>
<div style=" color: #172b4d; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 16px; letter-spacing: -0.005em; line-height: 1.714; margin-top: 10px; padding: 0px; white-space: pre-wrap;"> </div>
<ul>
    <li><span style="letter-spacing: -0.08px;">Watch <a href="https://www.youtube.com/watch?v=jVKGYu0_OCA">the video</a>.&nbsp;</span></li>
    <li><span style="font-size: 1em; letter-spacing: -0.005em;">Read the </span><a href="https://docs.datomic.com/cloud/analytics/analytics-concepts.html" style="font-size: 1em; letter-spacing: -0.005em;">Cloud docs</a><span
            style="font-size: 1em; letter-spacing: -0.005em;">.</span></li>
    <li>Read the <a href="https://docs.datomic.com/on-prem/analytics/analytics-concepts.html" style="font-size: 1em; letter-spacing: -0.005em;">On-Prem docs</a><span style="font-size: 1em; letter-spacing: -0.005em;">.</span></li>
</ul>

  ]]>
	</description>
    </item>
    <item>
      <title>Tuples and Database Predicates</title>
      <link>https://blog.datomic.com/2019/06/tuples-and-database-predicates.html</link>
      <pubDate>Tue, 28 May 2019 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2019/06/tuples-and-database-predicates.html</guid>
      	<description>
        <![CDATA[
	Today's releases of <a href="https://docs.datomic.com/cloud/index.html">Datomic Cloud</a> and <a href="https://docs.datomic.com/on-prem/index.html">Datomic On-Prem</a> include two major new features: tuples and &nbsp;database predicates.<br /><br />Tuples are a new compound data type, small vectors as values. You can use tuples to create multi-attribute unique keys on domain entities. You can also use tuples to optimize queries that otherwise would have to join two or more high-population attributes.<br /><ul><li>If you declare a <i>composite</i> tuple, Datomic will automatically populate the tuple from existing attributes.&nbsp;</li><li>You can also define your own homogeneous or heterogeneous tuple types that you populate as you see fit.</li></ul>Database predicates are functions and attribute lists that constrain the values accepted by transactions.<br /><ul><li>Attribute predicates are declared in schema and constrain the values taken on by a single attribute, in all contexts.&nbsp; For example, you could limit a <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">test/grade</span> attribute to the range 0-100.</li><li>Entity specs comprise lists of required attributes and/or predicates of the entity and the post-transaction db. You can use entity specs to ensure properties across different attributes of an entity or even across entities.&nbsp; For example, you might enforce that a game player's <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">score/lowest</span> must be less than or equal to their <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">score/highest</span>.&nbsp; You must explicitly call for entity specs in transactions in which you want them to apply.</li></ul><div>To learn more about tuples, database predicates, and other enhancements:</div><div><ul><li>Read the release announcement for <a href="https://forum.datomic.com/t/datomic-cloud-480-8770/1042">Datomic Cloud 480-8770</a>.</li><li>Read the release announcement for <a href="https://forum.datomic.com/t/datomic-0-9-5927-now-available/1040">Datomic On-Prem 0.9.5927</a>.</li></ul></div><br /><br />

  ]]>
	</description>
    </item>
    <item>
      <title>Return Maps</title>
      <link>https://blog.datomic.com/2019/06/return-maps-for-datomic-cloud-clients.html</link>
      <pubDate>Sat, 18 May 2019 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2019/06/return-maps-for-datomic-cloud-clients.html</guid>
      	<description>
        <![CDATA[
	Most <a href="https://datomic.com/">Datomic</a> queries return tuples, but sometimes you just want maps.&nbsp; <a href="https://forum.datomic.com/t/new-cloud-client-release-0-8-78/1024">Today's release</a> of the Datomic Cloud client library adds return maps to Datomic datalog.&nbsp; For example, the following query uses the new <b><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">:keys</span></b> clause to request maps with <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:artist</b></span> and <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:release</b></span>&nbsp;keys:<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14.4px; overflow: auto; padding: 5pt;">[<span style="color: darkslateblue;">:find</span> ?artist-name ?release-name<br /> <span style="color: darkslateblue;">:keys</span> artist release<br /> <span style="color: darkslateblue;">:where</span> [?release <span style="color: darkslateblue;">:release/name</span> ?release-name]<br /> [?release <span style="color: darkslateblue;">:release/artists</span> ?artist]<br /> [?artist <span style="color: darkslateblue;">:artist/name</span> ?artist-name]]</pre><br />Running against the <a href="https://github.com/Datomic/mbrainz-sample">mbrainz-sample</a> database, this query returns:<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14.4px; overflow: auto; padding: 5pt;">#{{<span style="color: darkslateblue;">:artist</span> <span style="color: #8b2252;">"George Jones"</span> <span style="color: darkslateblue;">:release</span> <span style="color: #8b2252;">"With Love"</span>}<br /> {<span style="color: darkslateblue;">:artist</span> <span style="color: #8b2252;">"Shocking Blue"</span> <span style="color: darkslateblue;">:release</span> <span style="color: #8b2252;">"Hello Darkness / Pickin' Tomatoes"</span>} <br /> {<span style="color: darkslateblue;">:artist</span> <span style="color: #8b2252;">"Junipher Greene"</span> <span style="color: darkslateblue;">:release</span> <span style="color: #8b2252;">"Friendship"</span>}<br /> ...}</pre><br />To try return maps, you can<br /><ul><li>Sign up for <a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa">Datomic Cloud on AWS Marketplace</a>.</li><li>Read the new <a href="https://docs.datomic.com/cloud/query/query-data-reference.html#return-maps">return maps docs</a>.</li></ul><br /><br />

  ]]>
	</description>
    </item>
    <item>
      <title>HTTP Direct for Datomic Cloud</title>
      <link>https://blog.datomic.com/2019/05/http-direct-for-datomic-cloud.html</link>
      <pubDate>Tue, 23 Apr 2019 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2019/05/http-direct-for-datomic-cloud.html</guid>
      	<description>
        <![CDATA[
	<br /><ul class="org-ul" style="-webkit-text-stroke-width: 0px; color: black; font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"></ul><br /><div style="-webkit-text-stroke-width: 0px; color: black; font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"><a href="https://www.datomic.com/">Datomic Cloud</a> is designed to be a <a href="https://docs.datomic.com/cloud/operation/architecture.html#applications">complete solution for Clojure application development</a> on AWS. In particular, you can implement web services as <a href="https://docs.datomic.com/cloud/ions/ions.html">Datomic ions</a> behind AWS API Gateway.</div><div style="-webkit-text-stroke-width: 0px; color: black; font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"><br /></div><div style="-webkit-text-stroke-width: 0px; color: black; font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">The latest release of Datomic Cloud adds HTTP Direct, which lets you connect an API Gateway endpoint directly to a <a href="https://docs.datomic.com/cloud/operation/architecture.html#production-topology">Production Topology Compute Group</a> as shown below:&nbsp;</div><div style="-webkit-text-stroke-width: 0px; color: black; font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"><br /></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><a href="/images/blog/-q5k81rwmfBc/XN281Kd8L9I/AAAAAAAAARI/CeONlx4EG-8PMViGZN5pM1lZlx6d6rD9QCLcBGAs/s1600/application-consumers.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="570" data-original-width="1600" src="/images/blog/-q5k81rwmfBc/XN281Kd8L9I/AAAAAAAAARI/CeONlx4EG-8PMViGZN5pM1lZlx6d6rD9QCLcBGAs/s1600/application-consumers.png" /></a><br /><div class="separator" style="clear: both; text-align: center;"></div><div style="font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px;"><br class="Apple-interchange-newline" />HTTP Direct provides better performance and simpler operation than AWS Lambda Proxy Integration. The latter option continues to be supported on the <a href="https://docs.datomic.com/cloud/operation/architecture.html#solo-topology">Solo Topology</a>, which does not include the Network Load Balancer required for HTTP Direct.</div><div style="font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px;"><br /></div><div style="font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px;">To try out HTTP Direct:</div><div style="font-family: &quot;Open Sans&quot;, sans-serif; font-size: 16px;"></div><ol><li>Get the <a href="https://docs.datomic.com/cloud/releases.html#current">latest release</a> of Datomic Cloud.</li><li>Work through the <a href="https://docs.datomic.com/cloud/livetutorial/http-direct.html">HTTP Direct Tutorial</a>.</li></ol><br /><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Valcache for Datomic On-Prem</title>
      <link>https://blog.datomic.com/2018/10/valcache.html</link>
      <pubDate>Sun, 9 Sep 2018 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2018/10/valcache.html</guid>
      	<description>
        <![CDATA[
	Everything gets better when data moves closer to processing. <a href="https://www.datomic.com/">Datomic</a> can extensively cache its immutable data without concern for coordination or invalidation. With the 'valcache' feature in today's Datomic On-Prem release you can use your local SSDs as large, durable per-process caches, on both transactors and peers. Valcache can improve performance, reduce the read load on storage and stay hot across process restarts.<br /><br /><ul></ul><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-4sZwll9D3Mk/W7YOPYiShPI/AAAAAAAAAPY/SBlR07xnM9gIUQDZftjbFsVeG4uwp32DwCLcBGAs/s1600/valcache.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="461" data-original-width="768" src="/images/blog/-4sZwll9D3Mk/W7YOPYiShPI/AAAAAAAAAPY/SBlR07xnM9gIUQDZftjbFsVeG4uwp32DwCLcBGAs/s1600/valcache.png" /></a></div><div><br /></div><div><br /></div><br />To get started with Valcache for&nbsp; Datomic On-Prem:<br /><br /><ul><li><a href="https://my.datomic.com/login">Get the latest release</a> of Datomic.</li><li>Read the <a href="https://docs.datomic.com/on-prem/valcache.html">Valcache docs</a>.&nbsp;</li></ul>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Query Groups</title>
      <link>https://blog.datomic.com/2018/09/query-groups.html</link>
      <pubDate>Tue, 7 Aug 2018 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2018/09/query-groups.html</guid>
      	<description>
        <![CDATA[
	A&nbsp;<a href="https://www.datomic.com/" target="_blank">Datomic</a>&nbsp;system can grow to meet the needs of your applications with query groups.<br /><br />Query groups provide one or more applications in a system with independent, elastically scalable query resources and working set caches. You can deploy different <a href="https://docs.datomic.com/cloud/ions/ions.html" target="_blank">Datomic Ion</a> applications to different query groups.<br /><br />Query groups can host different application development stages, each running their own revision of an Ion application.<br /><br /><div><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-aZsqutkmZaE/W5KQv0VXWxI/AAAAAAAAAOw/BeCePUbcdVMpp6vrGSmi5Caki6tKisavQCLcBGAs/s1600/multi-application.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="807" data-original-width="1342" src="/images/blog/-aZsqutkmZaE/W5KQv0VXWxI/AAAAAAAAAOw/BeCePUbcdVMpp6vrGSmi5Caki6tKisavQCLcBGAs/s1600/multi-application.png" /></a></div><div><br /></div><div><div>To learn more about query groups, read the new&nbsp;<a href="https://docs.datomic.com/cloud/operation/growing-your-system.html" target="_blank">Growing Your System</a>&nbsp;documentation.</div></div></div><div><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf" target="_blank"><br /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf" target="_blank"><img alt="Datomic Cloud on AWS Marketplace" border="0" data-original-height="140" data-original-width="760" height="72" src="/images/blog/-RWCSBWdNFAI/W5KWNVJjBFI/AAAAAAAAAPE/91y92LJM1rUb_UDKji_XJFCtA8EyzYYqACLcBGAs/s400/aws-marketplace.png" width="400" /></a></div><div style="text-align: center;"><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf" target="_blank">Datomic Cloud on AWS Marketplace</a></div><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Parameterizing Datomic Ion Applications</title>
      <link>https://blog.datomic.com/2018/08/ion-parameters.html</link>
      <pubDate>Sun, 15 Jul 2018 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2018/08/ion-parameters.html</guid>
      	<description>
        <![CDATA[
	Today's <a href="https://www.datomic.com/" target="_blank">Datomic Cloud</a> release provides an easy way to parameterize <a href="http://blog.datomic.com/2018/06/datomic-ions.html" target="_blank">ion applications</a>.<br /><h3>Rationale</h3><div>At runtime, applications need access to configuration data such as the name of a Datomic database. There are several challenges to consider:<br /><br /><ul><li>Configuration values have a lifecycle that is independent of application source code. They should not be hard-coded in the application, and should be managed separately from source code.</li><li>Applications need a way to obtain their configuration values at runtime.</li><li>Configuration values may be sensitive, and should not be stored or conveyed as plaintext.</li></ul><div>Parameters are a solution to these challenges.</div><h3>Ion Parameters</h3><div style="text-align: right;"></div>Before running your app, you store parameter values under hierarchical keys in&nbsp;<a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html" target="_blank">AWS Systems Manager Parameter Store</a>.&nbsp;At runtime, your app uses our new APIs to form the keys and read the values. This provides:<br /><ul><li>independent lifecycle for parameter values</li><li>encryption for sensitive data</li><li>granular IAM permissions</li></ul><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div></div><h3>Get Started</h3><div>To get started using Datomic's parameter support:</div><div><ul><li><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa" target="_blank">Sign up for Datomic</a> on the AWS Marketplace.</li><li>Learn more about ions from this <a href="https://www.youtube.com/watch?v=TbthtdBw93w" target="_blank">short video</a>.</li><li>Read the new <a href="https://docs.datomic.com/cloud/ions/ions-reference.html#parameters" target="_blank">Ion Parameters documentation</a>.</li></ul></div><div class="separator" style="clear: both; text-align: center;"></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Cloud Monitoring and Ion Cast</title>
      <link>https://blog.datomic.com/2018/07/datomic-ion-cast.html</link>
      <pubDate>Mon, 11 Jun 2018 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2018/07/datomic-ion-cast.html</guid>
      	<description>
        <![CDATA[
	The new datomic.ion.cast library lets your application produce monitoring data that are integrated with <a href="https://www.datomic.com/" target="_blank">Datomic</a>'s support for AWS CloudWatch.<br /><h4>Datomic Cloud and AWS CloudWatch</h4>AWS CloudWatch provides a powerful set of tools for monitoring a software system running on AWS:<br /><ul><li>Collect and track <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html" target="_blank">CloudWatch Metrics</a> -- variables that measure the behavior of your system.</li><li>Configure <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html" target="_blank">CloudWatch Alarms</a>&nbsp;to notify operations or take other automated steps when potential problems arise.</li><li>Monitor, store, and search <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html" target="_blank">CloudWatch Logs</a>&nbsp;across all your AWS resources.</li><li>Create <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Dashboards.html" target="_blank">CloudWatch Dashboards</a>&nbsp;that provide a single overview for monitoring your systems.</li></ul>Datomic Cloud is fully integrated with all of these AWS monitoring tools. On the producing side, Datomic creates <a href="https://docs.datomic.com/cloud/operation/monitoring.html#metrics" target="_blank">metrics</a> and <a href="https://docs.datomic.com/cloud/operation/monitoring.html#logs" target="_blank">logs</a>; and on the consuming side, Datomic organizes metrics in custom <a href="https://docs.datomic.com/cloud/operation/monitoring.html#dashboards" target="_blank">dashboards</a> like this Production Dashboard:<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="/images/blog/-109XXHedhlY/WnOUIygZswI/AAAAAAAAAMc/6yCkVC4ykEQf8bh9uDjIOKonysv_gsL1gCPcBGAYYCw/s1600/production-dashboard.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="830" data-original-width="1600" src="/images/blog/-109XXHedhlY/WnOUIygZswI/AAAAAAAAAMc/6yCkVC4ykEQf8bh9uDjIOKonysv_gsL1gCPcBGAYYCw/s1600/production-dashboard.png" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Production Dashboard</td></tr></tbody></table><br /><div><h4>datomic.ion.cast</h4></div><div>With the introduction of <a href="https://docs.datomic.com/cloud/ions/ions.html" target="_blank">Datomic Ions</a>, your entire application can run on Datomic Cloud nodes. The <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>datomic.ion.cast</b></span> namespace lets Ion application code add your own monitoring data alongside the monitoring data already being produced by Datomic.&nbsp; Cast supports four categories of monitoring data:</div><div><div><ol><li>An event is an ordinary occurence that is of interest to an operator, such as start and stop events for a process or activity.</li><li>An alert is an extraordinary occurrence that requires operator intervention, such as the failure of some important process.</li><li>Dev is information of interest only to developers, e.g. fine-grained logging to troubleshoot a problem during development. Dev data can be much higher volume than events or alerts.</li><li>A metric is a numeric value in a named time series, such as the latency for an operation.</li></ol></div><div>To get started using ion.cast, you can</div></div><div><ul><li><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa" target="_blank">sign up for Datomic</a> on the AWS Marketplace</li><li>learn about Datomic Ions in <a href="https://www.youtube.com/watch?v=TbthtdBw93w" target="_blank">this short video</a></li><li>read the new <a href="https://docs.datomic.com/cloud/ions/ions-monitoring.html" target="_blank">Monitoring Ions</a> documentation</li></ul></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Ions: Your App on Datomic Cloud</title>
      <link>https://blog.datomic.com/2018/06/datomic-ions.html</link>
      <pubDate>Sun, 6 May 2018 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2018/06/datomic-ions.html</guid>
      	<description>
        <![CDATA[
	<div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKsE8tE4BzI4I6Y81tt18aJtwCPcB/s1600/DatomicLogo_Square.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="199" src="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKsE8tE4BzI4I6Y81tt18aJtwCPcB/s200/DatomicLogo_Square.png" width="200" /></a></div>Datomic Ions let you develop applications for the cloud by deploying your code to a running Datomic cluster. You can <b>focus on your application logic</b>, writing ordinary Clojure functions, and the ion tooling and infrastructure handles the deployment and execution details. You can leverage your code both inside Datomic transactions and queries, and from the world at large via built-in support for AWS Lambda.<br /><br />With Datomic Ions you can:<br /><ul><li>Focus on your application</li><li>Leverage your Datomic Cloud cluster compute resources and data locality</li><li>Extend Datomic transactions and queries with your own logic</li><li>Connect to the broader AWS cloud via Lambda events</li><li>Service web consumers with API Gateway</li><li>Scale Datomic and your app together</li><li>Deliver on AWS with high agility</li></ul><br /><div>To learn more about ions, check out the <a href="https://docs.datomic.com/cloud/ions/ions.html" target="_blank">Datomic Cloud Ions documentation</a>.</div><div><br /></div><div>For Datomic On-Prem, we have added <a href="https://docs.datomic.com/on-prem/reference/database-functions.html#classpath-functions" target="_blank">classpath functions</a> and auto-require support for transaction functions and <a href="https://docs.datomic.com/on-prem/query/query.html#calling-clojure" target="_blank">query expressions</a>.</div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf"><br /><span style="border-image: initial; border-radius: 4px; clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="70" data-original-width="380" src="/images/blog/-RxcRgwasB3c/Wl0jyzGrOJI/AAAAAAAAAYI/i4KkQsM4BtUCkg3MwRME5ihyDNZ1DhvcwCLcBGAs/s1600/aws-marketplace-380x70.png" style="border-radius: 4px; border: 1px solid rgb(199, 199, 199);" /></span></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf">Datomic Cloud on the AWS Marketplace</a></td></tr></tbody></table>

  ]]>
	</description>
    </item>
    <item>
      <title>Important Security Update For free: and dev: Storage Protocols</title>
      <link>https://blog.datomic.com/2018/03/important-security-update.html</link>
      <pubDate>Thu, 1 Mar 2018 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2018/03/important-security-update.html</guid>
      	<description>
        <![CDATA[
	<span style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 14px;">Release 0.9.5697 fixes two security vulnerabilities in Datomic On-Prem transactors running the free: or dev: storage protocol.</span><br /><span style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 14px;"><br /></span><span style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 14px;">For more information, see the <a href="https://forum.datomic.com/t/important-security-update-0-9-5697/379" target="_blank">release announcement</a>.</span><br /><span style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 14px;"><br /></span><span style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 14px;">The Datomic team would like to thank&nbsp;</span><span style="color: #555555; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 14px;">Caio Vargas,&nbsp;</span><span style="color: #555555; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 14px;">Matheus Bernardes, and Nubank for reporting this issue.</span><br /><div><span style="color: #555555;"><br /></span></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Access Control in Datomic Cloud</title>
      <link>https://blog.datomic.com/2018/02/access-control-in-datomic-cloud.html</link>
      <pubDate>Fri, 19 Jan 2018 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2018/02/access-control-in-datomic-cloud.html</guid>
      	<description>
        <![CDATA[
	In this article, we will look at <a href="https://www.datomic.com/" target="_blank">Datomic</a> access control, covering<br /><ul><li>authentication and authorization</li><li>network-level access</li><li>how the bastion works</li><li>some example deployments</li></ul><h3>Authentication and Authorization</h3>Datomic integrates with AWS <a href="https://aws.amazon.com/iam" target="_blank">Identity and Access Management</a> (IAM) for authentication and authorization, via a technique that we'll call S3 proxying. Here's how it works:<br /><br />Every Datomic permission has a hierarchical name. For example, read-only access to database <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">Jan</span>&nbsp;is named <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">access/dbs/db/Jan/read</span>.<br /><br />Permission names have a 1-1 correspondence with keys in the Datomic <a href="https://docs.datomic.com/cloud/operation/architecture.html#storage-resources" target="_blank">system S3 bucket</a>.<br /><br />The Datomic client signs requests using AWS's <a href="https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html" target="_blank">Signature Version 4</a>. But instead of using your IAM credentials directly, the Datomic client uses your IAM credentials to retrieve a signing key from S3.<br /><br />Thus, IAM read permissions of S3 paths act as proxies for Datomic permissions. As a result, you can use all of the ordinary IAM tools (roles, groups, users, policies, etc.) to authorize use of Datomic.<br /><br />After decades of experience with racing to log into new servers to change the admin password, we think that this "secure by default" is pretty cool. But that is not the end of the story, as clients also must have network-level access to Datomic.<br /><h3>Network-Level Access</h3>Datomic Cloud is designed to be accessed by applications running inside a VPC, and (unlike a service!) is never exposed to the Internet. You must make an explicit choice to access Datomic. You could:<br /><br /><ul><li>run an EC2 instance in the Datomic VPC and in the Datomic applications security group</li><li><a href="https://docs.aws.amazon.com/AmazonVPC/latest/PeeringGuide/Welcome.html" target="_blank">peer another VPC</a> with the Datomic VPC&nbsp;</li><li>configure a <a href="https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpn-connections.html" target="_blank">VPN Connection</a></li></ul><br />Each of these approaches has its place for application access, and I will say more about them in a future article. For easy access to Datomic from a developer's laptop we offer the bastion.<br /><h3>How the Bastion Works</h3>The <a href="https://docs.datomic.com/cloud/operation/bastion.html" target="_blank">bastion</a> is a dedicated machine with one job only: to enable developer access to Datomic. When you turn the bastion on, you get a barebones AWS Linux instance that does exactly one thing: forwards SSH traffic to your Datomic system.<br /><br />To connect through the bastion:<br /><ol><li>run the&nbsp;<a href="https://docs.datomic.com/cloud/getting-started/connecting.html#socks-proxy" target="_blank">Datomic socks proxy script</a>&nbsp;on your local machine</li><li>add a proxy port argument when <a href="https://docs.datomic.com/cloud/getting-started/connecting.html#use-datomic" target="_blank">creating a system client</a></li><li>the Datomic client sees the proxy port argument and connects to the socks proxy&nbsp;</li><li>the socks proxy forwards encrypted SSH traffic to the bastion&nbsp;</li><li>the bastion forwards Datomic client protocol traffic to Datomic</li></ol><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-T2tD9ClQURw/WoYOD0QyIVI/AAAAAAAAANI/NJv4Qoe0QYglfPhmrLtup8Du-Q1-oeZCwCLcBGAs/s1600/bastion-access.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="422" data-original-width="1368" src="/images/blog/-T2tD9ClQURw/WoYOD0QyIVI/AAAAAAAAANI/NJv4Qoe0QYglfPhmrLtup8Du-Q1-oeZCwCLcBGAs/s1600/bastion-access.png" /></a></div><br />Access to the bastion is secured using the same IAM + S3 proxying technique used earlier for auth. The bastion has an auto-generated, ephemeral private key that is stored in S3 and secured by IAM.<br /><br />The bastion is dynamic, and you can <a href="https://docs.datomic.com/cloud/operation/bastion.html#starting-and-stopping" target="_blank">turn it on or off</a> an any time. And the client support means that the bastion is entirely transparent to your code, which differs only in the argument used to create the client.<br /><h3>A Concrete Example</h3>As a concrete example, here is how the <a href="https://twitter.com/datomic_team" target="_blank">Datomic team</a> configures access for some of our Datomic systems:<br /><br />Our 'ci' system is dedicated to continuous integration, supporting several dozen Jenkins projects. The ci system contains no sensitive data, only canned and generated examples. The ci system runs the <a href="https://docs.datomic.com/cloud/operation/architecture.html#solo-topology" target="_blank">Solo Topology</a> with the bastion enabled to allow access by automated tests.<br /><br />Our 'devdata' system contains non-sensitive data used by the development team (think departmental and sample apps). The devdata system runs the Solo Topology with the bastion enabled to allow access by developers.<br /><br />Our 'applications' system supports applications and contains real-world data. The applications system is reachable only by deployed application code, and needs to be highly available. So the applications system uses the <a href="https://docs.datomic.com/cloud/operation/architecture.html#production-topology" target="_blank">Production Topology</a> with the bastion disabled, and also uses fine-grained IAM permissions to limit applications to the databases they need.<br /><h3>Conclusion</h3>Datomic is secure by default, integrating directly with AWS IAM and VPC capabilities. The bastion makes it easy for developers to get connected, so you can be up and transacting on a new system in minutes.<br /><br />To learn more, check out<br /><ul><li>my <a href="https://www.datomic.com/videos.html" target="_blank">videos</a> of setting up a Datomic Cloud system</li><li>the&nbsp;<a href="https://docs.datomic.com/cloud/operation/access-control.html" target="_blank">access control</a> docs</li><li>the <a href="https://docs.datomic.com/cloud/operation/bastion.html" target="_blank">bastion</a> docs</li></ul><br />Or just <a href="https://docs.datomic.com/cloud/setting-up.html" target="_blank">dive in</a> and get started.<br /><br />

  ]]>
	</description>
    </item>
    <item>
      <title>High Availability in Datomic Cloud</title>
      <link>https://blog.datomic.com/2018/01/high-availability-in-datomic-cloud.html</link>
      <pubDate>Sun, 24 Dec 2017 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2018/01/high-availability-in-datomic-cloud.html</guid>
      	<description>
        <![CDATA[
	<div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; padding: 0px;">Based on my rigorous polling, these are the top five questions people have about HA in <a href="http://datomic.com/" target="_blank">Datomic Cloud</a>:</div><ul style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin: 10px 0px 0px;"><li>How does it work?</li><li>What do I have to do?</li><li>Hey wait a minute! What about serializability?</li><li>Is AWS cool?</li><li>So what else have you got?</li></ul><h2 style=" color: #333333; font-size: 14px; margin-top: 10px; padding: 0px;"><span style="font-size: 16px;">How Does It Work?</span></h2><div class="separator" style="clear: both; text-align: left;"><span style=" color: #333333; font-size: 14px;">In the <a href="https://docs.datomic.com/cloud/operation/architecture.html#production-topology" target="_blank">Production Topology</a>, Datomic cluster nodes sit behind an Application Load Balancer (ALB). As any node can handle any request, there is no single point of failure. The starting cluster size of two ensures that nodes remain available in the face of a single node failure. By increasing the cluster size beyond two, you both enhance availability and increase the number of queries the system can handle. An AutoScaling Group (ASG) monitors nodes and automatically replaces nodes that fail to health check.</span></div><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-tQ_iRSp9o74/WmjJUy8xmkI/AAAAAAAAAL0/PyyXXxUE7fMFVQfqLkMoOwpGdTUfqqe5wCLcBGAs/s1600/query-144-100.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="676" data-original-width="1600" src="/images/blog/-tQ_iRSp9o74/WmjJUy8xmkI/AAAAAAAAAL0/PyyXXxUE7fMFVQfqLkMoOwpGdTUfqqe5wCLcBGAs/s1600/query-144-100.png" /></a></div><div class="separator" style="clear: both; text-align: left;"><span style=" color: #333333; font-size: 14px;"><br /></span></div><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;"><div class="separator" style="clear: both; text-align: center;"></div></div><h2 style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;"><span style="font-size: 16px;">What Do I Have To Do?</span></h2><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">Nothing. HA is automatic.</div><h2 style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 16px; line-height: 1.5; margin: 30px 0px 0px; padding: 0px;">Hey Wait a Minute! What About Serializability?</h2><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">We <a href="http://datomic.com/" target="_blank">really like transactions</a>:</div><blockquote style=" border-left: 1px solid rgb(204, 204, 204); color: #707070; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin: 10px 0px 0px 19px; padding: 10px 20px;"><div style="padding: 0px;"><span style="color: #333333;">Datomic is always transactional, fully serialized, and consistent in both the ACID and CAP senses. Don't waste your life writing code to compensate for partial failures and subtle concurrency bugs when you could be making your application better and shipping it faster.</span></div></blockquote><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">So how does that square with shared-nothing cluster nodes? The answer is simple: The nodes use DynamoDB to serialize all writes per database.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-_KGCQ-wrZik/Wmiro33YlBI/AAAAAAAAALQ/nLZWcVUlmRAJxaNbYmINXkLIq-vY-MC_wCLcBGAs/s1600/tx-ha-300-50.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="676" data-original-width="1600" src="/images/blog/-_KGCQ-wrZik/Wmiro33YlBI/AAAAAAAAALQ/nLZWcVUlmRAJxaNbYmINXkLIq-vY-MC_wCLcBGAs/s1600/tx-ha-300-50.png" /></a></div></div><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">At any point in time a database has a preferred node for transactions. In normal operation all transactions for a database will flow to/through that node. If for any reason (e.g. a temporary network partition) the preferred node can't be reached, <i>any</i> node can and will handle transactions. Consistency is ensured by <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.ConditionalUpdate" target="_blank">conditional writes</a> to DynamoDB. If a node becomes unreachable, Datomic will choose a new preferred node.</div><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">Note in particular that:</div><ol style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin: 10px 0px 0px;"><li>This is not a master/follower system like <a href="https://docs.datomic.com/on-prem/operation/ha.html" target="_blank">Datomic On-Prem</a> and many other databases – nobody is tracking mastership and there are no failover intervals.</li><li>This should not be confused with parallel multi-writer systems such as Cassandra. Write availability is governed by the availability of DynamoDB conditional writes and <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.ReadConsistency.html" target="_blank">strongly-consistent reads</a>.</li></ol><h2 style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 16px; line-height: 1.5; margin: 30px 0px 0px; padding: 0px;">Is AWS Cool?</h2><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">Very cool. Datomic Cloud showcases the benefit of designing for AWS vs. porting to AWS, and there is a lot going on behind zeroconf HA:</div><ul style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin: 10px 0px 0px;"><li><a href="https://aws.amazon.com/cloudformation/" target="_blank">CloudFormation</a> automates creation and updates the cluster&nbsp;</li><li><a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html" target="_blank">Application Load Balancers</a> distribute requests transparently to clients</li><li><a href="https://aws.amazon.com/autoscaling/" target="_blank">Auto Scaling Groups</a> and health checks maintain a healthy cluster</li><li>DynamoDB conditional writes ensure transaction semantics</li></ul><h2 style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 16px; line-height: 1.5; margin: 30px 0px 0px; padding: 0px;">So What Else Have You Got?</h2><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">Not all systems need HA. You can prototype a Datomic Cloud system with the (non-HA) <a href="https://docs.datomic.com/cloud/operation/architecture.html#solo-topology" target="_blank">Solo Topology</a> for about $1/day.&nbsp; The topology differences are entirely abstracted away from clients and applications, so you can easily upgrade to the Production Topology later.</div><h2 style=" color: #333333; font-family: , , &quot;segoe ui&quot; , &quot;roboto&quot; , &quot;noto sans&quot; , &quot;ubuntu&quot; , &quot;droid sans&quot; , &quot;helvetica neue&quot; , sans-serif; font-size: 16px; line-height: 1.5; margin: 30px 0px 0px; padding: 0px;">For More Information:</h2><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">Check out the docs for</div><ul style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin: 10px 0px 0px;"><li><a href="https://docs.datomic.com/cloud/operation/ha.html" target="_blank">High Availability</a></li><li>the <a href="https://docs.datomic.com/cloud/operation/architecture.html" target="_blank">Production and Solo Topologies</a></li></ul><div style=" color: #333333; font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;">Or just <a href="https://docs.datomic.com/cloud/setting-up.html" target="_blank">jump right in</a>.</div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Cloud</title>
      <link>https://blog.datomic.com/2018/01/datomic-cloud.html</link>
      <pubDate>Sun, 17 Dec 2017 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2018/01/datomic-cloud.html</guid>
      	<description>
        <![CDATA[
	<div style=" margin-top: 10px; padding: 0px;"><span style="color: #333333; font-size: x-large;"><b>Datomic on AWS: Easy, Integrated, and Powerful</b></span><br /><span style="color: #333333; font-size: 14px;"><br /></span><span style="color: #333333; font-size: 14px;">We are excited to announce the release of&nbsp;</span><a href="http://www.datomic.com/" style="font-size: 14px;">Datomic Cloud</a><span style="color: #333333; font-size: 14px;">, making Datomic more accessible than ever before:</span></div><ul style=" font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin: 10px 0px 0px;"><li><strong style="color: #333333;">Easy</strong><span style="color: #333333;">:&nbsp;Datomic Cloud is an Amazon Marketplace AMI.&nbsp;</span><ul style="list-style-type: disc; margin: 0px;"><li style="margin-left: 0px;"><span style="color: blue;"><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf">click through</a></span><span style="color: #333333;">&nbsp;a CloudFormation wizard and you can be&nbsp;</span><a href="http://www.datomic.com/videos.html#setting-up-video">up and running in minutes</a></li><li style="margin-left: 0px;"><span style="color: #333333;">start with the&nbsp;</span><a href="http://docs.datomic.com/cloud/operation/architecture.html#solo-topology">Solo Topology</a><span style="color: #333333;">&nbsp;(including AWS instance) for about $1/day, billed hourly</span></li><li><a href="${config.pricinglink}">itemized</a><span style="color: navy;">&nbsp;on your&nbsp;</span><span style="color: #333333;">regular AWS bill</span></li></ul></li><li><strong style="color: #333333;">Integrated</strong><span style="color: #333333;">: Datomic Cloud is closely integrated with AWS,&nbsp;</span><em style="color: #333333;">automatically</em><span style="color: #333333;">&nbsp;providing:</span><ul style="list-style-type: disc; margin: 0px;"><li style="margin-left: 0px;"><span style="color: #333333;">encryption at rest with key management by&nbsp;</span><a href="https://aws.amazon.com/kms/">KMS</a></li><li style="margin-left: 0px;"><a href="http://docs.datomic.com/cloud/operation/ha.html">clustered high availability</a><span style="color: #333333;">&nbsp;behind&nbsp;</span><a href="https://aws.amazon.com/elasticloadbalancing/">Application Load Balancers</a><span style="color: #333333;">&nbsp;(ALBs)</span></li><li style="margin-left: 0px;"><a href="http://docs.datomic.com/cloud/operation/scaling.html"><em>elastic</em>&nbsp;read autoscaling</a><span style="color: #333333;">&nbsp;via&nbsp;</span><a href="https://aws.amazon.com/autoscaling/">autoscaling groups&nbsp;</a><span style="color: #333333;">without sharding</span></li><li style="margin-left: 0px;"><a href="http://docs.datomic.com/cloud/operation/architecture.html#storage-resources">redundant storage</a><span style="color: #333333;">&nbsp;across multiple highly-available, fault-tolerant storages:&nbsp;</span><a href="https://aws.amazon.com/dynamodb/">DynamoDB</a><span style="color: #333333;">,&nbsp;</span><a href="https://aws.amazon.com/s3/">S3</a><span style="color: #333333;">, and&nbsp;</span><a href="https://aws.amazon.com/efs/">EFS</a></li><li style="margin-left: 0px;"><a href="https://aws.amazon.com/cloudwatch/">CloudWatch metrics and dashboards</a></li></ul></li><li style="margin-left: 0px;"><strong style="color: #333333;">Powerful:&nbsp;</strong><span style="color: #333333;">Datomic Cloud delivers the full Datomic information model</span><br /><ul style="list-style-type: disc; margin: 0px;"><li style="margin-left: 0px;"><a href="http://docs.datomic.com/cloud/transactions/acid.html">ACID transactions</a></li><li style="margin-left: 0px;"><a href="http://docs.datomic.com/cloud/query/query-data-reference.html">Datalog query</a><span style="color: #333333;">&nbsp;with joins, recursion, and rules</span></li><li style="margin-left: 0px;"><a href="http://docs.datomic.com/cloud/schema/schema-reference.html">a universal relation</a><span style="color: #333333;"> supporting row, column, entity, and graph access</span></li><li style="margin-left: 0px;"><a href="http://docs.datomic.com/cloud/whatis/data-model.html#accumulate-only">indelible</a>, <a href="http://docs.datomic.com/cloud/whatis/data-model.html#time-model">chronological</a><span style="color: #333333;">&nbsp;storage so you can track data over time</span></li></ul></li></ul><div style=" font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;"><span style="color: #333333;">Datomic Cloud is a new product intended for greenfield development on AWS. If you are not yet targeting the cloud, check out what&nbsp;</span><a href="http://www.datomic.com/customers.html">customers are saying</a><span style="color: blue;">&nbsp;</span><span style="color: #333333;">about the established line of Datomic On-Prem products (Datomic Pro and Enterprise).</span></div><div style=" font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;"><a href="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKs6ORN66PZFARUe2W1zinMoQCPcBGAYYCw/s1600/DatomicLogo_Square.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="" border="0" data-original-height="451" data-original-width="451" height="100" src="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKs6ORN66PZFARUe2W1zinMoQCPcBGAYYCw/s200/DatomicLogo_Square.png" title="" width="100" /></a><span style="color: #333333;">Datomic Cloud is accessible through the latest release of the&nbsp;</span><a href="http://docs.datomic.com/cloud/client/client-api.html">Datomic Client API</a><span style="color: blue;">.&nbsp;<span style="color: black;">To learn more, you can</span>:</span></div><ul style=" font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin: 10px 0px 0px;"><li><a href="http://www.datomic.com/videos.html#setting-up-video">see</a><span style="color: #333333;">&nbsp;how to set up in minutes</span></li><li><a href="http://docs.datomic.com/cloud/setting-up.html">try it yourself</a></li><li><a href="http://docs.datomic.com/cloud/operation/architecture.html">learn more</a><span style="color: #333333;">&nbsp;about the architecture</span></li><li><span style="color: #333333;">review the&nbsp;</span><a href="http://docs.datomic.com/on-prem/cloud/moving-to-cloud.html">differences</a><span style="color: #333333;">&nbsp;between Cloud and On-Prem</span></li></ul><div style=" font-family: -apple-system, system-ui, &quot;Segoe UI&quot;, Roboto, &quot;Noto Sans&quot;, Ubuntu, &quot;Droid Sans&quot;, &quot;Helvetica Neue&quot;, sans-serif; font-size: 14px; margin-top: 10px; padding: 0px;"><span style="color: #333333;">We would love your feedback! Come and join us on the new&nbsp;</span><a href="http://forum.datomic.com/">developer forum</a><span style="color: #333333;">.</span></div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf"><br /><span style="border-image: initial; border-radius: 4px; clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="70" data-original-width="380" src="/images/blog/-RxcRgwasB3c/Wl0jyzGrOJI/AAAAAAAAAYI/i4KkQsM4BtUCkg3MwRME5ihyDNZ1DhvcwCLcBGAs/s1600/aws-marketplace-380x70.png" style="border-radius: 4px; border: 1px solid rgb(199, 199, 199);" /></span></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><a href="https://aws.amazon.com/marketplace/pp/prodview-otb76awcrb7aa?ref=vdr_rf">Datomic Cloud on the AWS Marketplace</a></td></tr></tbody></table>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Pull :as</title>
      <link>https://blog.datomic.com/2017/12/datomic-pull-as.html</link>
      <pubDate>Sun, 5 Nov 2017 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2017/12/datomic-pull-as.html</guid>
      	<description>
        <![CDATA[
	<a href="http://datomic.com/" target="_blank">Datomic</a>'s <a href="http://docs.datomic.com/pull.html" target="_blank">Pull API</a> provides a declarative way to make hierarchical and nested selections of information about entities.&nbsp; The 0.9.5656 release enhances the Pull API with a new <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">:as</span> clause that provides control over the returned keys.<br /><br />As an example, imagine that you want information about Led Zeppelin's tracks from the <a href="https://github.com/Datomic/mbrainz-sample" target="_blank">mbrainz dataset</a>. The following pull pattern navigates to the artist's tracks, using <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">limit</span> to return a single track:<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14.4px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">pull expression</span><br />'[[<span style="color: darkslateblue;">:track/_artists</span> <span style="color: darkslateblue;">:limit</span> 1]]<br /><br />=&gt; #<span style="color: darkslateblue;">:track</span>{<span style="color: darkslateblue;">:_artists</span><br /> [#<span style="color: darkslateblue;">:db</span>{<span style="color: darkslateblue;">:id</span> 17592188757937}]}</pre><br />The entity id&nbsp;<span style="color: #38c202; font-family: &quot;courier&quot;; font-size: 16px;">17592188757937</span>&nbsp;is not terribly interesting, so you can use a nested pull pattern to request the track name instead:<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14.4px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">pull pattern</span><br />'[{[<span style="color: darkslateblue;">:track/_artists</span> <span style="color: darkslateblue;">:limit</span> 1] [<span style="color: darkslateblue;">:track/name</span>]}]<br /><br />=&gt; #<span style="color: darkslateblue;">:track</span>{<span style="color: darkslateblue;">:_artists</span> [#<span style="color: darkslateblue;">:track</span>{<span style="color: darkslateblue;">:name</span> <span style="color: #8b2252;">"Black Dog"</span>}]}</pre><div class="p2"><span class="s2"><br /></span></div>That is better, but what if you want different key names? This can happen for reasons including:<br /><br /><ul><li>you are targeting an environment that does not support symbolic names, so you need a string instead of a keyword key</li><li>you do not want to expose the <a href="http://docs.datomic.com/pull.html#reverse-lookup" target="_blank">direction of navigation</a> (e.g. the underscore in :<span style="color: #431579; font-family: &quot;courier&quot;; font-size: 16px;">track/_artists)</span></li><li>your consumers are expecting a different name</li></ul><div>The <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">:as</span> option lets you rename result keys to arbitrary values that you provide, and works at any level of nesting in a pull pattern. The pattern below uses <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">:as</span> twice to rename the two keys in the result:</div><div><br /></div><div><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14.4px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">pull expression</span><br />'[{[<span style="color: darkslateblue;">:track/_artists</span> <span style="color: darkslateblue;">:limit</span> 1 <span style="color: darkslateblue;">:as</span> <span style="color: #8b2252;">"Tracks"</span>]<br /> [[<span style="color: darkslateblue;">:track/name</span> <span style="color: darkslateblue;">:as</span> <span style="color: #8b2252;">"Name"</span>]]}]<br /><br />=&gt; {<span style="color: #8b2252;">"Tracks"</span> [{<span style="color: #8b2252;">"Name"</span> <span style="color: #8b2252;">"Black Dog"</span>}]}</pre></div><br /><div><br /></div><div>To try it out you can <a href="https://my.datomic.com/" target="_blank">grab the latest release</a>, review the <a href="http://docs.datomic.com/pull.html#grammar" target="_blank">Pull grammar</a>, and work through <a href="https://github.com/Datomic/day-of-datomic/blob/master/tutorial/pull.clj" target="_blank">these examples</a> at the REPL.</div><div><br /></div><div><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #1a76b6} span.s1 {color: #686868} span.s2 {color: #000000} span.s3 {color: #38c202} span.s4 {color: #1a76b6} </style> <br /><div class="p1"><br /></div></div><br /><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 22.0px Courier; color: #431579} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 22.0px Courier; color: #38c202} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #431579} </style><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #aaaaaa} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #38c202} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #431579} </style><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #aaaaaa} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #38c202} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #431579} </style><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #aaaaaa} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #38c202} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #431579} </style><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #aaaaaa} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #1a76b6} </style><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #aaaaaa} p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #1a76b6} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #1a76b6} </style><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #38c202} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #431579} </style><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #1a76b6} </style><style type="text/css">p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #007742} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #431579} p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 16.0px Courier; color: #1a76b6} span.s1 {color: #aaaaaa} span.s2 {color: #686868} span.s3 {color: #000000} span.s4 {color: #38c202} span.s5 {color: #1a76b6} </style>

  ]]>
	</description>
    </item>
    <item>
      <title>New Datomic Training Videos and Getting Started Documentation</title>
      <link>https://blog.datomic.com/2017/03/new-datomic-training-videos-and-getting.html</link>
      <pubDate>Thu, 23 Feb 2017 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2017/03/new-datomic-training-videos-and-getting.html</guid>
      	<description>
        <![CDATA[
	<div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKsE8tE4BzI4I6Y81tt18aJtwCPcB/s1600/DatomicLogo_Square.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="199" src="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKsE8tE4BzI4I6Y81tt18aJtwCPcB/s200/DatomicLogo_Square.png" width="200" /></a></div>We are excited to announce the release of a new set of <a href="http://www.datomic.com/training.html">Day of Datomic training videos</a>!<br />Filmed at Clojure/Conj in Austin, TX in December of 2016, this series covers everything from the architecture and data model of Datomic to operation and scaling considerations.<br /><br />The new training sessions provide a great foundation for developing a Datomic-based system. For those of you who have watched the original Day of Datomic videos, the series released today uses the new <a href="http://blog.datomic.com/2016/11/datomic-update-client-api-unlimited.html">Datomic Client library</a> for the examples and workshops, so if you haven't yet explored Datomic Clients, now is the perfect opportunity to do so!<br /><br />If you ever want to refer back to the original Peer-based training videos, don't worry - they're all still available as well.<br /><br />In addition to an updated Day of Datomic, we've released a fully re-organized and re-written <a href="http://docs.datomic.com/getting-started/brief-overview.html">Getting Started</a> section in the <a href="http://docs.datomic.com/">Datomic Documentation</a>. We have gathered and incorporated feedback from new and existing users and hope that the new Getting Started is a much more comprehensive and accessible introduction to Datomic.<br /><br />We look forward to your thoughts and feedback. If you have any comments on the <a href="http://www.datomic.com/training.html">new training videos</a>, the <a href="http://docs.datomic.com/getting-started/brief-overview.html">new getting started section,</a> or any additional thoughts, please let us know!

  ]]>
	</description>
    </item>
    <item>
      <title>The Ten Rules of Schema Growth</title>
      <link>https://blog.datomic.com/2017/01/the-ten-rules-of-schema-growth.html</link>
      <pubDate>Sun, 25 Dec 2016 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2017/01/the-ten-rules-of-schema-growth.html</guid>
      	<description>
        <![CDATA[
	Data outlives code, and a valuable database supports many applications over time. These ten rules will help grow your database schema without breaking your applications.<br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKsE8tE4BzI4I6Y81tt18aJtwCPcB/s1600/DatomicLogo_Square.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="199" src="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKsE8tE4BzI4I6Y81tt18aJtwCPcB/s200/DatomicLogo_Square.png" width="200" /></a></div><h3>1. &nbsp;Prod is not like dev.</h3>Production is not development. In production, one or more codebases depend on your data, and these ten rules below should be followed exactingly.<br /><br />A dev environment can be much more relaxed. &nbsp;Alone on your development machine experimenting with a new feature, you have no users to break. &nbsp;You can soften the rules, so long as you harden them when transitioning to production.<br /><h3>2. &nbsp;Grow your schema, and never break it.</h3>The lack of common vocabulary makes it all too easy to automate the wrong practices. I will use the terms <i>growth</i> and <i>breakage</i> as defined in Rich Hickey's&nbsp;<a href="https://www.youtube.com/watch?v=oyLBGkS5ICk" target="_blank">Spec-ulation</a>&nbsp;talk. &nbsp;In schema terms:<br /><br /><ul><li><i>growth</i> is providing more schema</li><li><i>breakage</i> is removing schema, or changing the meaning of existing schema.</li></ul><br />In contrast to these terms, many people use "<a href="http://edgeguides.rubyonrails.org/active_record_migrations.html" target="_blank">migrations</a>", "<a href="http://databaserefactoring.com/" target="_blank">refactoring</a>", or "<a href="https://martinfowler.com/articles/evodb.html" target="_blank">evolution</a>". These usages tend to focus on repeatability, convenience, and the needs of new programs, ignoring the distinction between growth and breakage. The problem here is obvious: Breakage is bad, so we don't want it to be more convenient!<br /><br />Using precise language underscores the costs of of breakage. Most migrations are easily categorized as growth or breakage by considering the rules below. &nbsp;<i>Growth migrations</i> are suitable for production, and <i>breakage migrations</i> are, at best, a dev-only convenience. Keep them widely separate.<br /><h3>3. The database is the source of truth.</h3>Schema growth needs to be reproducible from one environment to another. &nbsp;Reproducibility supports the development and testing of new schema before putting it into production and also the reuse of schema in different databases. Schema growth also needs to be evident in the database itself, so that you can determine what the database has, what it needs, and when growth occurred.<br /><br />For both of these reasons, the database is the proper source of truth for schema growth. When the database is the source of truth, reproducability and auditability happen <i>for free</i>&nbsp;via the ordinary<br />query and transaction capabilities of the database. &nbsp;(If your database is not up to the tasks of queries and transactions you have bigger problems beyond the scope of this article).<br /><br />Storing schema in a database is strictly more powerful than storing schema as text files in source control. The database is the actual home for schema, plus it provides validation, structure, query, transactions, and history. A source control system provides only history and is separate from the data itself.<br /><br />Note that this does <i>not</i> mean "never put schema information in source control". Source control may be convenient for other reasons, e.g. it may be more readily accessible. You may redundantly store schema in source control, but remember that the database is definitive.<br /><h3>4. &nbsp;Growing is adding.</h3>As you acquire more information about your domain, grow your schema to match. You can grow a schema by adding new things, and <i>only</i> by adding new things, for example:<br /><br /><ul><li>adding new attributes to an existing 'type'</li><li>adding new types</li><li>adding relationships between types</li></ul><div><br /></div><h3>5. &nbsp;Never remove a name.</h3>Removing a named schema component at any level is a breaking change for programs that depend on that name. Never remove a name.<br /><h3>6. &nbsp;Never reuse a name.</h3>The meaning of a name is established when the name is first introduced. Reusing that name to mean something substantially different breaks programs that depend on that meaning. This can be even<br />worse than removing the name, as the breakage may not be as immediately obvious.<br /><h3>7. &nbsp;Use aliases.</h3>If you are familiar with database refactoring patterns, the advice in Rules Five and Six may seem stark. After all, one purpose of refactoring is to adopt better names as we discover them. How can we<br />do that if names can never be removed or changed in meaning?<br /><br />The simple solution is to use <a href="http://docs.datomic.com/schema.html#renaming-an-identity" target="_blank">more than one alias</a> to refer to the same schema entity. Consider the following example:<br /><br /><ul><li>In iteration 1, users of your system are identified by their email with an attribute named <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/id</b></span>.&nbsp;</li><li>In iteration 2, you discover that users sometimes have non-email identifiers for users and that you want to store a user's email even when not using the email as an identifier. In short, you wish that <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/id</b></span>&nbsp;was named <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/primary-email</b></span>.</li></ul><br />No problem! Just create <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/primary-email</b></span> as an alias for <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/id</b></span>. Older programs can continue to use <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/id</b></span>, and newer programs can use the now-preferred <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/primary-email</b></span>.<br /><h3>8. &nbsp;Namespace all names.</h3>Namespaces greatly reduce the cost of getting a name wrong, as the same local name can safely have different meanings in different namespaces. &nbsp;Continuing the previous example, imagine that the local<br />name <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>id</b></span> is used to refer to a UUID in several namespaces, e.g. <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:inventory/id</b></span>, <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:order/id</b></span>, and so on. The fact that <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/id&nbsp;</b></span>is <i>not</i> a UUID is inconsistent, and newer programs should not have to put up with this.<br /><br />Namespaces let you improve the situation without breaking existing programs. You can introduce <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user-v2/id</b></span>, and new programs can ignore names in the&nbsp;<b><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">user</span></b>&nbsp;namespace. If you don't like <b><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">v2</span></b>, you can also pick a more semantic name for the new namespace.<br /><h3>9. &nbsp;Annotate your schema.</h3>Databases are good at storing data about your schema. Adding annotations to your schema can help both human readers and make sense of how the schema grew over time. For example:<br /><br /><ul><li>you could annotate names that are not recommended for new programs with a <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:schema/deprecated</b></span> flag, or you could get fancier still with <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:schema/deprecated-at</b></span> or <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:schema/deprecated-because</b></span>. Note that such deprecated names are still <i>never</i> removed (Rule Five).</li><li>you could provide <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:schema/see-also</b></span> or <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:schema/see-instead</b></span> pointers to more current conventions.&nbsp;</li></ul><br />In fact, all the database refactoring patterns that are typically implemented as breaking changes could be implemented non-destructively, with the refactoring details recorded as an annotation. For example, the breaking <a href="http://databaserefactoring.com/SplitColumns.html" target="_blank">"split column" refactoring</a>&nbsp;might instead be implemented as schema growth:<br /><br /><ul><li>add N new columns</li><li>(optional) add a <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:schema/split-into</b></span> attribute on the original column whose value is the new columns, and possibly even the recipe for the split</li></ul><div><br /></div><h3>10. Plan for accretion.</h3>If a system is going to grow at all, then programs must not bake in limiting presumptions. &nbsp;For example: If a schema states that <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/id</b></span> is a string, then programs can rely on <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;"><b>:user/id</b></span> being a string and not occasionally an integer or a boolean. &nbsp;But a program cannot assume that a user entity will be limited to a the set of attributes previously seen, or that it understands the semantics of attributes that it has not seen before.<br /><h3>Are these rules specific to a particular database?</h3>No. These rules apply to almost any SQL or NoSQL database. &nbsp;The rules even apply to the so-called "schemaless" databases. &nbsp;A better word for schemaless is "schema-implicit", i.e. the schema is implicit in your data and the database has no reified awareness of it. &nbsp;With an implicit schema, all the rules still apply, except that the database is impotent to help you (no Rule 3).<br /><h3>In Context</h3>Many of the resources on migrations, refactoring, and database evolution emphasize repeatability and the needs of new programs, without making the top-level distinctions of growth vs. breakage and prod vs. dev. As a result, these resources encourage breaking the rules in this article.<br /><br />Happily, these resources can easily be recast in growth-only terms. &nbsp;You <i>can</i> grow your schema without breaking your app. You <i>can</i> continuously deploy without continuously propagating breakage. &nbsp;Here's what it looks like <a href="http://docs.datomic.com/best-practices.html#production-schema" target="_blank">in Datomic</a>.<br /><br /><br />

  ]]>
	</description>
    </item>
    <item>
      <title>Customer Feedback Portal</title>
      <link>https://blog.datomic.com/2016/12/customer-feedback-portal.html</link>
      <pubDate>Mon, 14 Nov 2016 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2016/12/customer-feedback-portal.html</guid>
      	<description>
        <![CDATA[
	Receptive has been closed, and feature requests moved to the <a href="https://ask.datomic.com">Datomic Knowledgebase</a>.

The rest of this post is left for posterity.

<hr>>

As part of our commitment to improving Datomic, a few weeks ago we enabled a new feature request and user feedback system, Receptive.io, where you can help us prioritize our efforts and help shape the future of Datomic.<br /><br /><a href="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKsE8tE4BzI4I6Y81tt18aJtwCPcB/s1600/DatomicLogo_Square.png" imageanchor="1" style="clear: right; display: inline !important; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="120" src="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAANQ/MmACZ8DAbKsE8tE4BzI4I6Y81tt18aJtwCPcB/s200/DatomicLogo_Square.png" width="120" /></a>To submit your feature request follow the "Suggest Features" link in the top navigation of the <a href="http://my.datomic.com/" target="_blank">my.datomic.com</a>&nbsp;dashboard. We have already connected your account to Receptive.io so everything is set up and ready for you to go.<br /><br />You can read more about using Receptive <a href="https://help.receptive.io/hc/en-us/articles/210845605-How-to-suggest-features-with-Receptive" target="_blank">here</a>.<br /><br />-The Datomic Team

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Update: Client API, Unlimited Peers, Enterprise Edition, and More</title>
      <link>https://blog.datomic.com/2016/11/datomic-update-client-api-unlimited.html</link>
      <pubDate>Fri, 28 Oct 2016 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2016/11/datomic-update-client-api-unlimited.html</guid>
      	<description>
        <![CDATA[
	We are pleased to announce that the latest (0.9.5530) release of Datomic includes a set of new features and licensing changes to address needs identified by our customers:<br /><ul><a href="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAAM8/Lw2H5qG-D4Md5W43UoqkemvyDYQB0JGmgCLcB/s1600/DatomicLogo_Square.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="10" height="150" src="/images/blog/-53l7suMbyss/WDw4_QYOk5I/AAAAAAAAAM8/Lw2H5qG-D4Md5W43UoqkemvyDYQB0JGmgCLcB/s200/DatomicLogo_Square.png" width="150" /></a><li>In addition to the peer model, Datomic now includes a <a href="http://docs.datomic.com/clients-and-peers.html" target="_blank">Client API</a> suitable for smaller, short lived processes, e.g. microservices.</li><li>The various tiers of the Datomic Pro license model have been simplified to a <a href="http://www.datomic.com/get-datomic.html" target="_blank">single license</a> with no restriction on peer count.</li><li>We have introduced an <a href="http://www.datomic.com/get-datomic.html" target="_blank">Enterprise license tier</a> for users who need customized pricing, support, or licensing terms.</li><li><a href="http://docs.datomic.com/transactions.html#temporary-ids" target="_blank">Tempids</a> and explicit <a href="http://docs.datomic.com/schema.html#partitions" target="_blank">partitions</a> are now optional, simplifying code for the many programs that do not care about them.</li><li>Schema install and update are now implicit, and do not require <a href="http://docs.datomic.com/schema.html#explicit-schema" target="_blank">explicit</a> :db.install/attribute or :db.update/attribute datoms.</li></ul><br />The features described above are additive and opt-in, so take advantage of them as and when you please.<br /><br />Each of these changes is described in more detail below.<br /><div><br /><h3>Building On a Solid Foundation</h3><br />Before talking about what is new, it is important to talk about what is unchanged. We built Datomic believing that the <a href="http://www.datomic.com/rationale.html">Rationale</a> is a sound foundation for an information system, and experience has proven this out. We have not retracted a word of the rationale since day one, and are not doing so today. Datomic’s core ideas are unchanged:<br /><ul><li>getting time, process, and perception right</li><li>sound data model</li><li>ACID transactions</li><li>Datalog query</li><li>minimal schema</li><li>separate reads and writes</li><li>programming with data</li></ul><br />Datomic has delivered these ideas with a discipline that minimizes breaking API change. As a result, Datomic users have been able to focus on their business problems without having to worry about changing semantics in their database.</div><div><br /><h3>Client API</h3><br />Datomic’s peer library puts database query in your own application process. This provides several benefits, but at the price of a heavier dependency (both in code and in memory requirements) than a traditional client.<br /><br />A smaller footprint is useful in environments that have operational limitations, or where processes are small or short-lived. The new Datomic client API addresses this need. Lightweight clients connect to <a href="http://docs.datomic.com/peer-server.html" target="_blank">Peer Servers</a>, which are peers that run in a separate address space.<br /><br />Existing peers are unchanged, and you can mix and match peer and client applications as you see fit within the same Datomic install. Clients and peers are described in detail in the new <a href="http://docs.datomic.com/clients-and-peers.html" target="_blank">clients and peers</a>&nbsp;section of the docs.</div><div><br /></div>With today’s release, we are making available the alpha version of the open source Client library for Clojure. The Java library will be released shortly. We also have plans to both create more language libraries for Client and enable our customers to create their own. We are interested in your feedback on the Client API itself and the priority of our language reach efforts. As of today, we have enabled a customer feedback portal, accessible via the "Suggest Features" link in the top navigation of the <a href="http://my.datomic.com/">my.datomic.com</a> dashboard, where you can help us prioritize our efforts in this (and many other) areas.<br /><div><br /><h3>Unlimited Peers</h3><br />Flexibility in Peer use has been the most often-requested update to Datomic. You are solving complex problems using cutting edge technologies and architectures. Your tools should allow you to design the system that best fits your needs.  Datomic’s new licensing model gives all users - Starter, Pro and Enterprise - the ability to design for and deploy as many Peer processes (and Clients!) as their systems require. Today’s release represents a massive upgrade to the potential of each (new and existing) Datomic installation.</div><div><h3></h3><h3>Pro Starter License</h3><br />The Pro Starter license provides a no-cost way to try Datomic. You get a perpetual license plus a year of software upgrades for free. Starting with this release, Pro Starter includes all the features of a Pro license, including<br /><ul><li>unlimited peers</li><li>clients</li><li>High Availability (HA)</li><li>integrated memcached</li></ul><div><br /></div><h3>Enterprise Tier</h3><br />Datomic has a number of enterprise customers already. They distinguish themselves by wanting<br /><ul><li>custom license terms</li><li>custom pricing for larger installations</li><li>custom support terms</li><li>custom development</li></ul><br />If you match one or more of these criteria, <a href="http://www.datomic.com/contact.html" target="_blank">contact us</a> to discuss an Enterprise license.</div><div><br /></div><h3>Tempid and Partition Defaults</h3><div><br />Datomic’s tempids provide a way to <a href="http://docs.datomic.com/schema.html#partitions" target="_blank">partition</a> new entities, encoding a locality hint directly in transactions. This feature is powerful, but rarely used, and the API and data structure for tempids are an inconvenience for the majority of users, who do not need or want partition control.<br /><br />Starting with the current release of Datomic:<br /><ul><li><a href="http://docs.datomic.com/transactions.html#temporary-ids" target="_blank">tempids</a> are optional</li><li>when you need a tempid to coordinate the relationship between two entities, you can use an ordinary string instead of a tempid structure, and that string can be meaningful to readers of your code</li><li>the existing tempid data structure and API continue to be supported unchanged. Use them if you want them.</li></ul><br />Clients will support string tempids only.</div><div><h3></h3><h3>Schema Install and Update</h3><br />Transactions that change attribute schema must include either :db.install/attribute (to create an attribute) or:db.alter/attribute (to change an existing attribute). The new release of Datomic <a href="http://docs.datomic.com/schema.html#explicit-schema" target="_blank">infers the need</a> for these datoms and adds them to your transaction automatically, reducing the verbosity of schema data.</div><div><h3></h3><h3>Conclusion</h3><br />We are very excited about the additions and changes to Datomic. To celebrate, we will be offering a 20% discount on new Datomic purchases through the end of February 2017. We hope you take advantage of the new features and this discount opportunity and please feel free to reach out to us at anytime.</div>

  ]]>
	</description>
    </item>
    <item>
      <title>Log API for Memory Databases</title>
      <link>https://blog.datomic.com/2016/08/log-api-for-memory-databases.html</link>
      <pubDate>Sun, 10 Jul 2016 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2016/08/log-api-for-memory-databases.html</guid>
      	<description>
        <![CDATA[
	The most recent <a href="https://groups.google.com/d/topic/datomic/QLdZ_WePR5A/discussion">Datomic Release</a> provides access to the Datomic <a href="http://docs.datomic.com/log.html">Log API</a> for memory databases. I would like to take this opportunity to describe some of the features and uses of the Datomic Log API.<br /><br />The transactional log is a fundamental component of <a href="http://docs.datomic.com/acid.html">ACID</a> database systems, a durable record of the transactions performed by the database. In addition to its critical function in ensuring ACID semantics, the Datomic log, as a sequential (in database time, <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">t</span>) record of all transactions, also functions as a time-ordered index to the data stored in a Datomic database.<br /><br />Datomic provides access to the transaction log directly via the <a href="http://docs.datomic.com/clojure/#datomic.api/tx-range"><i>tx-range</i> function</a> and from within query using the <a href="http://docs.datomic.com/log.html#log-in-query"><i>tx-ids</i> and <i>tx-data</i> functions</a>.<br /><br />An <a href="https://github.com/Datomic/day-of-datomic/blob/master/tutorial/log.clj">example</a>&nbsp;using the log in query is now available in the <a href="https://github.com/Datomic/day-of-datomic">Day of Datomic</a> repo. Our example database records the streets on which our three protagonists, John, Mary, and Joe, live.<br /><br />Let’s find out when Joe moved to Broadway:<br /><br /><pre class="src src-clojure">(<span style="color: #008700;">d</span>/q '[<span style="color: #008787;">:find</span> ?tx<br /> <span style="color: #008787;">:in</span> $ ?name ?street<br /> <span style="color: #008787;">:where</span><br /> [?e <span style="color: #008787;">:person/name</span> ?name]<br /> [?e <span style="color: #008787;">:person/street</span> ?street ?tx <span style="color: #008787;">true</span>]]<br /> (<span style="color: #008700;">d</span>/history (<span style="color: #008700;">d</span>/db conn)) <span style="color: #87005f;">"Joe"</span> <span style="color: #87005f;">"Broadway"</span>)<br /></pre><br />This query returns <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">13194139534317</span>, the transaction ID of the transaction that asserted Joe’s street is Broadway. As in all Datomic databases, every transaction also records a timestamp, the <i>:db/txInstant</i>. Let’s see what wall-clock time is associated with this transaction entity:<br /><br /><pre class="src src-clojure">(<span style="color: #008700;">d</span>/pull (<span style="color: #008700;">d</span>/db conn) '[<span style="color: #008787;">:db/txInstant</span>] 13194139534317)<br /></pre><br />So Joe moved to Broadway in 1983.<br /><br />Issuing queries against the transaction log is a powerful approach for auditing the operational history of a database. Because <a href="http://blog.datomic.com/2015/12/reified-transactions.html">every transaction is an entity</a> in Datomic, we can easily retrieve the entire set of datoms for a given transaction entity. Let’s find out what else happened in the ‘Joe moves to Broadway’ transaction. This query returns all the datoms associated with the given transaction: <br /><br /><pre class="src src-clojure">(<span style="color: #008700;">d</span>/q '[<span style="color: #008787;">:find</span> ?e ?a ?v ?tx ?op<br /> <span style="color: #008787;">:in</span> ?log ?tx<br /> <span style="color: #008787;">:where</span> [(tx-data ?log ?tx)[[?e ?a ?v _ ?op]]]]<br /> (<span style="color: #008700;">d</span>/log conn) 13194139534317)<br /><br /><span style="color: #af0000;">;; </span><span style="color: #af0000;">result:</span><br />#{[17592186045420 64 <span style="color: #87005f;">"2nd"</span> 13194139534317 <span style="color: #008787;">true</span>]<br /> [17592186045419 64 <span style="color: #87005f;">"Broadway"</span> 13194139534317 <span style="color: #008787;">true</span>]<br /> [13194139534317 50 #inst<span style="color: #87005f;">"1983-01-01T00:00:00.000-00:00"</span> 13194139534317 <span style="color: #008787;">true</span>]<br /> [17592186045420 64 <span style="color: #87005f;">"Elm"</span> 13194139534317 <span style="color: #008787;">false</span>]<br /> [17592186045419 64 <span style="color: #87005f;">"1st"</span> 13194139534317 <span style="color: #008787;">false</span>]}<br /></pre><br />Note that we see the same wall clock time we found previously as well as 4 other datoms. One is the assertion of Joe moving to Broadway, one is the retraction of his previous street (1st), and the remaining two datoms are about someone else entirely. Let’s find out who:<br /><br /><pre class="src src-clojure">(<span style="color: #008700;">d</span>/pull (<span style="color: #008700;">d</span>/db conn) '[*] 17592186045420)<br /><br /><span style="color: #af0000;">;; </span><span style="color: #af0000;">result:</span><br />{<span style="color: #008787;">:db/id</span> 17592186045420, <span style="color: #008787;">:person/name</span> <span style="color: #87005f;">"Mary"</span>, <span style="color: #008787;">:person/street</span> <span style="color: #87005f;">"2nd"</span>}<br /></pre><br />By using the log, we’ve determined that Mary’s move to 2nd Street was recorded at the same time (during the same transaction) as Joe's move to Broadway.<br /><br />The ability to query the Datomic transaction log directly is a powerful tool for managing, administering, and using a Datomic database. The addition of the Log API to memory databases enables low-overhead testing and evaluation of Datomic’s Log API feature. We hope you find the Log API on memory databases a helpful addition for lightweight development and unit testing.

  ]]>
	</description>
    </item>
    <item>
      <title>You Might Not Need an ORM</title>
      <link>https://blog.datomic.com/2016/04/you-might-not-need-orm.html</link>
      <pubDate>Wed, 23 Mar 2016 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2016/04/you-might-not-need-orm.html</guid>
      	<description>
        <![CDATA[
	Over the last few months, my colleague Michael Nygard has been writing&nbsp;<a href="http://blog.cognitect.com/blog/?tag=NewNormal+Series" target="_blank">The New Normal</a> series over on the <a href="http://blog.cognitect.com/" target="_blank">Cognitect blog</a>, arguing that our industry needs to embrace continuous partial failure and aim to build <a href="http://blog.cognitect.com/blog/2016/2/18/the-new-normal-from-resilient-to-antifragile" target="_blank">antifragile</a> systems.<br /><br />In his&nbsp;<a href="http://blog.cognitect.com/blog/2016/4/22/the-new-normal-everything-relies-on-sharp-tools" target="_blank">most recent installment</a>, Mike shares some ideas on sharp tools and their value in eliminating code. Mike worked with several teams that considered object-relational mapping (ORM) for <a href="http://datomic.com/" target="_blank">Datomic</a>, concluding that with Datomic, you don't need ORM at all. Datomic lets you eliminate an entire architectural layer from your applications.

  ]]>
	</description>
    </item>
    <item>
      <title>Reified Transactions</title>
      <link>https://blog.datomic.com/2015/12/reified-transactions.html</link>
      <pubDate>Tue, 3 Nov 2015 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2015/12/reified-transactions.html</guid>
      	<description>
        <![CDATA[
	Domain data often answers the question "what", e.g.<br /><ul><li>What products are in inventory?</li><li>What users have accounts on the system?</li><li>What tests have been run?</li></ul><div>But many domains also include information about the provenance of data, e.g.</div><div><ul><li>Who said this data was correct?</li><li>When should this data be published?</li><li>Where did this data come from?</li><li>Why was this correction necessary?</li></ul><div>How should you model this "data about data"? Datomic stores (and lets you store) facts about transactions themselves. In other words, transactions are themselves <i>reified</i> as data in the system.</div></div><div><br /></div><div>Tim Ewald gave a great talk about this at Datomic Conf. His talk and all the other Datomic Conf talks are now freely available <a href="http://www.datomic.com/videos.html" target="_blank">online</a>.</div>

  ]]>
	</description>
    </item>
    <item>
      <title>CQRS with Clojure, Kafka, and Datomic</title>
      <link>https://blog.datomic.com/2015/11/cqrs-with-clojure-kafka-and-datomic.html</link>
      <pubDate>Sat, 24 Oct 2015 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2015/11/cqrs-with-clojure-kafka-and-datomic.html</guid>
      	<description>
        <![CDATA[
	<a href="http://datomic.com/" target="_blank">Datomic</a>'s <a href="http://docs.datomic.com/architecture.html" target="_blank">clean separation of reads and writes</a> has inspired many comparisons with the <a href="http://martinfowler.com/bliki/CQRS.html" target="_blank">CQRS</a> (Command and Query Responsibility Segregation) architectural pattern.<br /><br />One person who has traveled far down this road is Bobby Calderwood, a member of the Technology Fellows team at Capital One. Check out his recent <a href="https://www.youtube.com/watch?v=qDNPQo9UmJA" target="_blank">Clojure/conj talk</a>, where he demonstrates a complete CQRS implementation using <a href="http://clojure.org/" target="_blank">Clojure</a> microservices, Kafka, and Datomic.

  ]]>
	</description>
    </item>
    <item>
      <title>Yeller chooses Datomic</title>
      <link>https://blog.datomic.com/2015/11/yeller-chooses-datomic.html</link>
      <pubDate>Mon, 5 Oct 2015 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2015/11/yeller-chooses-datomic.html</guid>
      	<description>
        <![CDATA[
	<a href="http://yellerapp.com/">Yeller</a> is an exception tracking service whose goal is to provide clear, actionable information to developers to take the pain out of examining application errors. They chose <a href="http://clojure.org/" target="_blank">Clojure</a> and <a href="http://datomic.com/" target="_blank">Datomic</a> as the platform for Yeller in order to make the development process more effective and more efficient.<br /><br />You can read all about their reasons for <a href="http://yellerapp.com/posts/2015-09-21-datomic-clojure-benefits.html">choosing Clojure and Datomic on their blog</a>. You can also watch <a href="https://www.youtube.com/watch?v=0tUrbf6Uzu8&amp;list=PLZdCLR02grLoBx0Y5ZrpdmLxc160PIwzQ&amp;index=17">Tom explain it all at EuroClojure 2015</a>.

  ]]>
	</description>
    </item>
    <item>
      <title>Nubank chooses Datomic</title>
      <link>https://blog.datomic.com/2015/09/nubank-chooses-datomic.html</link>
      <pubDate>Fri, 14 Aug 2015 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2015/09/nubank-chooses-datomic.html</guid>
      	<description>
        <![CDATA[
	Brazil is the world's 5th largest country in both area and population, has the 2nd most airports (behind the United States), and one of the highest credit card interest rates in the world. The Brazilian banking industry is both heavily regulated and extremely concentrated. Enter Nubank, whose founders have created a banking alternative in one of the world’s fastest growing mobile markets.<br /><br />Traditional software wasn’t going to get the job done for Nubank. From the very beginning, the goal was “differentiation through technology.” They needed to plan for growth, both in size and complexity, to meet constantly changing regulatory and business rules.<br /><br />Nubank turned to <a href="http://datomic.com/" target="_blank">Datomic</a> to access multiple data stores simultaneously, process transactions, and easily query historical data. Engineers can perform complex analyses on real-time data while the performance of the production environment is preserved. Along the way, the <a href="http://cognitect.com/" target="_blank">Cognitect</a> team helped steer Nubank’s engineers on the right path as they built Datomic into their business.<br /><br />Read the <a href="http://www.datomic.com/nubanks-story.html">full case study</a> to see how Datomic and <a href="http://clojure.org/" target="_blank">Clojure</a> are helping Nubank change the banking industry.

  ]]>
	</description>
    </item>
    <item>
      <title>A Conversational Introduction to Datomic</title>
      <link>https://blog.datomic.com/2015/08/a-conversational-introduction-to-datomic.html</link>
      <pubDate>Mon, 20 Jul 2015 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2015/08/a-conversational-introduction-to-datomic.html</guid>
      	<description>
        <![CDATA[
	My colleague Carin Meier has been writing up <a href="http://gigasquidsoftware.com/blog/2015/08/15/conversations-with-datomic/" target="_blank">her</a> <a href="http://gigasquidsoftware.com/blog/2015/08/19/conversations-with-datomic-part-2/" target="_blank">conversations</a> with <a href="http://datomic.com/" target="_blank">Datomic</a>, introducing the database via an imagined dialog between a new user and the database. &nbsp;In a very short space she introduces<br /><br /><ul><li>rapid development against a memory database</li><li><a href="http://docs.datomic.com/schema.html" target="_blank">schema</a> definition</li><li>hierarchical selection with <a href="http://docs.datomic.com/pull.html" target="_blank">pull</a></li><li>Datalog <a href="http://docs.datomic.com/query.html" target="_blank">query</a></li><li>strong <a href="http://docs.datomic.com/acid.html#consistency" target="_blank">consistency</a></li><li>retractions and <a href="http://docs.datomic.com/filters.html#history" target="_blank">history</a></li></ul><div>Carin puts all these ideas into context with examples that you can explore in minutes. &nbsp;If you are new to Datomic, check it out.</div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Best Practices</title>
      <link>https://blog.datomic.com/2015/07/datomic-best-practices.html</link>
      <pubDate>Sun, 7 Jun 2015 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2015/07/datomic-best-practices.html</guid>
      	<description>
        <![CDATA[
	We are happy to announce the addition of a <a href="http://docs.datomic.com/best-practices.html" target="_blank">Best Practices</a> section to the Datomic Development Resources documentation. The Best Practices topic is a tool to help users quickly find preferred usage patterns when approaching common scenarios in Datomic.<br /><br />The Datomic Best Practices documentation includes sections on:<br /><br /><ul><li><a href="http://docs.datomic.com/best-practices.html#datomic-schema" target="_blank">Designing Schema</a></li><li><a href="http://docs.datomic.com/best-practices.html#datomic-transaction" target="_blank">Transaction Strategies</a></li><li><a href="http://docs.datomic.com/best-practices.html#datomic-query" target="_blank">Building and Optimizing Queries</a></li><li><a href="http://docs.datomic.com/best-practices.html#datomic-time" target="_blank">Time in Datomic</a></li></ul><br />Where appropriate, examples are included as are links to the full documentation for further reading.<br /><br />See the <a href="http://docs.datomic.com/best-practices.html" target="_blank">Best Practices documentation</a> for the full list. We expect to add more subtopics to the Best Practices documentation over time, so check back periodically.<br /><br />We look forward to your feedback. If you have any comments on the new best practices topics, or any questions you think would be addressed by an additional topic, let us know!

  ]]>
	</description>
    </item>
    <item>
      <title>More Power for Datomic Datalog: Negation, Disjunction, and Range Optimizations</title>
      <link>https://blog.datomic.com/2015/01/datalog-enhancements.html</link>
      <pubDate>Sat, 13 Dec 2014 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2015/01/datalog-enhancements.html</guid>
      	<description>
        <![CDATA[
	<div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Today's <a href="http://datomic.com/" target="_blank">Datomic</a> release includes a number of enhancements to Datomic's Datalog query language:</div><ul style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin: 10px 0px 0px;"><li>Negation, via the new&nbsp;<i>not</i>&nbsp;and&nbsp;<i>not-join</i>&nbsp;clauses</li><li>Disjunction (<i>or</i>) without using rules, via the new&nbsp;<i>or</i>&nbsp;and&nbsp;<i>or-join</i>&nbsp;clauses</li><li>Required rule bindings</li><li>Improved optimization of range predicates</li></ul><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Each is described below, and you can follow the examples from the <a href="https://github.com/Datomic/mbrainz-sample" target="_blank">mbrainz data set</a> in <a href="https://github.com/Datomic/datomic-java-examples/blob/master/src/java/datomic/samples/Query.java" target="_blank">Java</a> or in <a href="https://github.com/Datomic/day-of-datomic/blob/master/tutorial/query.clj" target="_blank">Clojure</a>.&nbsp;</div><h3 id="MorePowerforDatomicDatalog:Negation,Disjunction,andRangeOptimizations-Negation" style=" color: #333333; font-family: Arial, sans-serif; font-size: 16px; line-height: 1.5; margin: 30px 0px 0px; padding: 0px;">Negation</h3><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">The&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">not</span><span style="font-family: Arial, sans-serif;">&nbsp;clause shrinks a result set, removing already-bound tuples whose variables match a set of clauses. &nbsp;</span></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">For example, the following query finds the names of all artists who are not Canadian:</div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); color: black; font-family: courier, monospace; line-height: normal; overflow: auto; padding: 5pt;">[<span style="color: darkslateblue;">:find</span> ?name<br /> <span style="color: darkslateblue;">:where</span> [?eid <span style="color: darkslateblue;">:artist/name</span> ?name]<br /> <span style="color: #8c8c8c;">(</span>not [?eid <span style="color: darkslateblue;">:artist/country</span> <span style="color: darkslateblue;">:country/CA</span>]<span style="color: #8c8c8c;">)</span>]</pre></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">The&nbsp;</span><span style="line-height: 1.4285715;"><span style="font-family: Courier New, Courier, monospace;">not-join</span></span><span style="font-family: Arial, sans-serif;">&nbsp;clause generalizes&nbsp;</span><span style="line-height: 1.4285715;"><span style="font-family: Courier New, Courier, monospace;">not</span></span><span style="font-family: Arial, sans-serif;">, and allows you to also specify which variables inside the&nbsp;</span><span style="line-height: 1.4285715;"><span style="font-family: Courier New, Courier, monospace;">not-join</span></span><span style="font-family: Arial, sans-serif;">&nbsp;will unify with the enclosing query.</span></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">The following query counts artists who did&nbsp;<i>not&nbsp;</i>release an album in 1970. &nbsp;The </span><span style="font-family: Courier New, Courier, monospace;">not-join</span><span style="font-family: Arial, sans-serif;"> specifies that </span><span style="font-family: Courier New, Courier, monospace;">?artist</span><span style="font-family: Arial, sans-serif;"> unifies with the containing query, and (implicitly) that </span><span style="font-family: Courier New, Courier, monospace;">?release</span><span style="font-family: Arial, sans-serif;"> is local.</span></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); color: black; font-family: courier, monospace; line-height: normal; overflow: auto; padding: 5pt;">[<span style="color: darkslateblue;">:find</span> <span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">count</span> ?artist<span style="color: #8c8c8c;">)</span> .<br /> <span style="color: darkslateblue;">:where</span> [?artist <span style="color: darkslateblue;">:artist/name</span>]<br /> <span style="color: #8c8c8c;">(</span>not-join [?artist]<br /> [?release <span style="color: darkslateblue;">:release/artists</span> ?artist]<br /> [?release <span style="color: darkslateblue;">:release/year</span> 1970]<span style="color: #8c8c8c;">)</span>]</pre></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">As elsewhere in Datomic Datalog, lists of clauses inside&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">not</span><span style="font-family: Arial, sans-serif;">&nbsp;or&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">not-join</span><span style="font-family: Arial, sans-serif;">&nbsp;are connected by an implicit&nbsp;</span><i style="font-family: Arial, sans-serif;">and</i><span style="font-family: Arial, sans-serif;">.&nbsp;</span></div><h3 style=" color: #333333; font-family: Arial, sans-serif; line-height: 20px; margin: 20px 0px 0px; padding: 0px;"><span style="font-size: small;">Disjunction</span></h3><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Datomic Datalog has long supported disjunction (<i>or</i>) via <a href="http://docs.datomic.com/query.html#rules" target="_blank">rules</a>. &nbsp;Rules are a powerful abstraction mechanism, allowing you to create named pieces of logic to be reused across multiple queries. &nbsp;Rules are also the path to recursion in query. &nbsp;But sometimes you don't need all that, and you just want simple disjunction in situ.</div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">The&nbsp;<i>o</i>r clause binds variables that match at least one of a set of predicates.</div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">As an example, consider the way mbrainz models release media. &nbsp; There are four separate enums that all represent vinyl:&nbsp;<i>vinyl</i>,&nbsp;<i>vinyl-7</i>,&nbsp;<i>vinyl-10</i>, and<i>vinyl-12. &nbsp;</i>An </span><span style="font-family: Courier New, Courier, monospace;">or</span><span style="font-family: Arial, sans-serif;"> clause can group these all together, finding all the vinyl releases:</span></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); color: black; font-family: courier, monospace; line-height: normal; overflow: auto; padding: 5pt;">[<span style="color: darkslateblue;">:find</span> <span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">count</span> ?medium<span style="color: #8c8c8c;">)</span> .<br /> <span style="color: darkslateblue;">:where</span> <span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">or</span> [?medium <span style="color: darkslateblue;">:medium/format</span> <span style="color: darkslateblue;">:medium.format/vinyl7</span>]<br /> [?medium <span style="color: darkslateblue;">:medium/format</span> <span style="color: darkslateblue;">:medium.format/vinyl10</span>]<br /> [?medium <span style="color: darkslateblue;">:medium/format</span> <span style="color: darkslateblue;">:medium.format/vinyl12</span>]<br /> [?medium <span style="color: darkslateblue;">:medium/format</span> <span style="color: darkslateblue;">:medium.format/vinyl</span>]<span style="color: #8c8c8c;">)</span>]</pre></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">The&nbsp;</span><i style="font-family: Arial, sans-serif;">and</i><span style="font-family: Arial, sans-serif;">&nbsp;clause is available as an explicit form inside&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">or</span><span style="font-family: Arial, sans-serif;">&nbsp;clauses. &nbsp;For example, the following query finds artists that are either groups or female individuals:</span></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); color: black; font-family: courier, monospace; line-height: normal; overflow: auto; padding: 5pt;">[<span style="color: darkslateblue;">:find</span> <span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">count</span> ?artist<span style="color: #8c8c8c;">)</span> .<br /> <span style="color: darkslateblue;">:where</span> <span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">or</span> [?artist <span style="color: darkslateblue;">:artist/type</span> <span style="color: darkslateblue;">:artist.type/group</span>]<br /> <span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">and</span> [?artist <span style="color: darkslateblue;">:artist/type</span> <span style="color: darkslateblue;">:artist.type/person</span>]<br /> [?artist <span style="color: darkslateblue;">:artist/gender</span> <span style="color: darkslateblue;">:artist.gender/female</span>]<span style="color: #8c8c8c;">))</span>]</pre></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">Note that&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">and</span><span style="font-family: Arial, sans-serif;">&nbsp;clauses are used only inside&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">or</span><span style="font-family: Arial, sans-serif;">&nbsp;– elsewhere in query,&nbsp;</span><i style="font-family: Arial, sans-serif;">and</i><span style="font-family: Arial, sans-serif;">&nbsp;is implicit wherever clauses appear sequentially.</span></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">The&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">or-join</span><span style="font-family: Arial, sans-serif;">&nbsp;clause&nbsp;is a generalization of&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">or</span><span style="font-family: Arial, sans-serif;">, just as&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">not-join</span><span style="font-family: Arial, sans-serif;">&nbsp;generalizes&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">not</span><span style="font-family: Arial, sans-serif;">.</span></div><h3 style=" color: #333333; font-family: Arial, sans-serif; line-height: 20px; margin: 20px 0px 0px; padding: 0px;"><span style="font-size: small;">All Together</span></h3><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Negation and disjunction can be nested, allowing direct expression of e.g. 'not this or that', e.g.</div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); color: black; font-family: courier, monospace; line-height: normal; overflow: auto; padding: 5pt;">[<span style="color: darkslateblue;">:find</span> ?name<br /> <span style="color: darkslateblue;">:where</span> [?eid <span style="color: darkslateblue;">:artist/name</span> ?name]<br /> <span style="color: #8c8c8c;">(</span>not <span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">or</span> [?eid <span style="color: darkslateblue;">:artist/country</span> <span style="color: darkslateblue;">:country/US</span>]<span style="color: #8c8c8c;">)</span><br /> [?eid <span style="color: darkslateblue;">:artist/country</span> <span style="color: darkslateblue;">:country/CA</span>]<span style="color: #8c8c8c;">)</span>]</pre></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">which means "find all the artists, except those that are from the US or Canada."</div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-size: 16px; font-weight: bold; line-height: 1.5;">Required Rule Bindings</span></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Rules are relational, and do not dictate the order in which variables are bound. &nbsp; Imagine a rule that finds tracks shorter than a certain maximum length for an artist. &nbsp;You might write that rule as:</div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); color: black; font-family: courier, monospace; line-height: normal; overflow: auto; padding: 5pt;">[<span style="color: #8c8c8c;">(</span>short-track ?a ?t ?len ?max<span style="color: #8c8c8c;">)</span><br /> [?t <span style="color: darkslateblue;">:track/artists</span> ?a]<br /> [?t <span style="color: darkslateblue;">:track/duration</span> ?len]<br /> [<span style="color: #8c8c8c;">(</span>&lt; ?len ?max<span style="color: #8c8c8c;">)</span>]]</pre></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">This rule does not tell the caller anything about when the four variables might be bound, revealing little about its use. &nbsp;You might try to</div><ul style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin: 10px 0px 0px;"><li>invoke the rule in a context where no variables are bound yet, finding all possible relationships</li><li>invoke the rule with all variables bound, as a predicate check</li><li>any combination of variable bindings between these two extremes&nbsp;</li></ul><div><span style="color: #333333; font-family: Arial, sans-serif;"><span style="font-size: 14px; line-height: 20px;"><br /></span></span></div><div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Often, complete flexibility in binding is exactly what you want. &nbsp;But in this case, the author of the rule has a specific intent:</div><ul style=" color: #333333; font-size: 14px; line-height: 20px; margin: 10px 0px 0px;"><li><span style="font-family: Courier New, Courier, monospace;">?max</span><span style="font-family: Arial, sans-serif;">&nbsp;is a <i>required</i> input, as nothing inside the rule knows how to manufacture a&nbsp;</span><span style="font-family: Courier New, Courier, monospace;">?max</span></li><li><span style="font-family: Courier New, Courier, monospace;">?a</span><span style="font-family: Arial, sans-serif;">&nbsp;is an intended input (this rule is about artists)</span></li></ul><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Rules can specify required vars in a list as the first element after the rule name. &nbsp;The rule head above can thus be rewritten as</div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); color: black; font-family: courier, monospace; line-height: normal; overflow: auto; padding: 5pt;"><span style="color: #8c8c8c;">(</span>short-track [?a ?max] ?t ?len<span style="color: #8c8c8c;">)</span></pre></div><div style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;">Now the </span><span style="font-family: Courier New, Courier, monospace;">?a</span><span style="font-family: Arial, sans-serif;"> and </span><span style="font-family: Courier New, Courier, monospace;">?max</span><span style="font-family: Arial, sans-serif;"> variables are required. Datomic will not invoke a rule until required variables are bound, and will throw an exception if they cannot be bound.</span></div><pre class="src src-clojure" style=" color: #333333; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif; font-size: 16px; font-weight: bold; line-height: 1.5;">Optimization of Range Predicates</span></pre><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Datomic now better leverages indexes to lookup range predicates (=, &lt;=, &gt;=, &lt;. and &gt;) where one argument is bound at the start of the query. &nbsp;For example, in the following query</div></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); color: black; font-family: courier, monospace; line-height: normal; overflow: auto; padding: 5pt;">[<span style="color: darkslateblue;">:find</span> <span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">count</span> ?artist<span style="color: #8c8c8c;">)</span> .<br /> <span style="color: darkslateblue;">:in</span> $ ?max-year<br /> <span style="color: darkslateblue;">:where</span> [?artist <span style="color: darkslateblue;">:artist/startYear</span> ?year]<br /> [<span style="color: #8c8c8c;">(</span>&lt; ?year ?max-year<span style="color: #8c8c8c;">)</span>]]</pre></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><span style="font-family: Arial, sans-serif;"><br /></span><span style="font-family: Arial, sans-serif;">Datomic will see that </span><span style="font-family: Courier New, Courier, monospace;">?max-year</span><span style="font-family: Arial, sans-serif;"> is bound, and use the AVET index on </span><span style="font-family: Courier New, Courier, monospace;">:artist/startYear</span><span style="font-family: Arial, sans-serif;"> to consider only datoms guaranteed to match the predicate. &nbsp;This can result in substantial speedups and reduced memory usage for queries that substantially limit results via range predicates.</span></div><h3 id="MorePowerforDatomicDatalog:Negation,Disjunction,andRangeOptimizations-Summary" style=" color: #333333; font-family: Arial, sans-serif; font-size: 16px; line-height: 1.5; margin: 30px 0px 0px; padding: 0px;">Summary</h3><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">Taken together, the new capabilities above add substantial expressive power and performance to Datomic Datalog. &nbsp;Get the full details <a href="http://docs.datomic.com/query.html" target="_blank">in the docs</a>, and happy querying!</div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><br /></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><br /></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><br /></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><br /></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><br /></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><br /></div><div style=" color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;"><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Pull API</title>
      <link>https://blog.datomic.com/2014/10/datomic-pull.html</link>
      <pubDate>Sun, 28 Sep 2014 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2014/10/datomic-pull.html</guid>
      	<description>
        <![CDATA[
	<a href="http://datomic.com/" target="_blank">Datomic</a>'s new Pull API is a declarative way to make hierarchical selections of information about entities. You supply a pattern to specify which attributes of the entity (and nested entities) you want to pull, and <span style="font-family: Courier New, Courier, monospace;">db.pull</span>&nbsp;returns a map for each entity.<br /><h4>Pull API vs. Entity API</h4>The Pull API has two important advantages over the existing <a href="http://docs.datomic.com/entities.html" target="_blank">Entity API</a>:<br /><br />Pull uses a declarative, data-driven spec, whereas Entity encourages building results via code. Data-driven specs are easier to build, compose, transmit and store. Pull patterns are smaller than entity code that does the same job, and can be easier to understand and maintain.<br /><br />Pull API results match standard collection interfaces (e.g. Java maps) in programming languages, where Entity results do not. This eliminates the need for an additional allocation/transformation step per entity. <br /><h4>Wildcards</h4>A pull pattern is a list of attribute specifications. &nbsp;If you want all attributes, you can use the wildcard (*) specification along with an <a href="http://docs.datomic.com/identity.html#entity-identifiers" target="_blank">entity identifier</a>. &nbsp;(In the examples below, entity identifiers such as <span style="font-family: Courier New, Courier, monospace;">led-zeppelin</span> are variables defined in the complete code examples in&nbsp;<a href="https://github.com/Datomic/day-of-datomic/blob/master/tutorial/pull.clj" target="_blank">Clojure</a>&nbsp;and&nbsp;<a href="https://github.com/Datomic/datomic-java-examples/blob/master/src/java/datomic/samples/Pull.java" target="_blank">Java</a>.)<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">Clojure API</span><br /><span style="color: #8c8c8c;">(</span>d/pull db '[*] led-zeppelin<span style="color: #8c8c8c;">)</span></pre><br /><pre class="src src-java" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">;; <span style="color: forestgreen;">Java API</span><br />db.<span style="color: blue;">pull</span>(<span style="color: #8b2252;">"[*]"</span>, <span style="color: forestgreen;">ledZeppelin</span>)</pre><br />A pull result is a map per entity, shown here in <a href="http://edn-format.org/" target="_blank">edn</a>:<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">result</span><br />{<span style="color: darkslateblue;">:artist/sortName</span> <span style="color: #8b2252;">"Led Zeppelin"</span>, <br /> <span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"Led Zeppelin"</span>, <br /> <span style="color: darkslateblue;">:artist/type</span> {<span style="color: darkslateblue;">:db/id</span> 17592186045746}, <br /> <span style="color: darkslateblue;">:artist/country</span> {<span style="color: darkslateblue;">:db/id</span> 17592186045576}, <br /> <span style="color: darkslateblue;">:artist/gid</span> #uuid <span style="color: #8b2252;">"678d88b2-87b0-403b-b63d-5da7465aecc3"</span>, <br /> <span style="color: darkslateblue;">:artist/endDay</span> 25, <br /> <span style="color: darkslateblue;">:artist/startYear</span> 1968, <br /> <span style="color: darkslateblue;">:artist/endMonth</span> 9, <br /> <span style="color: darkslateblue;">:artist/endYear</span> 1980, <br /> <span style="color: darkslateblue;">:db/id</span> 17592186050305}</pre><h4>Attributes</h4>You can also specify the attributes you want explicitly, as with <span style="font-family: Courier New, Courier, monospace;">:artist/name</span> and <span style="font-family: Courier New, Courier, monospace;">:artist/gid</span> below:<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">pattern</span><br />[<span style="color: darkslateblue;">:artist/name</span> <span style="color: darkslateblue;">:artist/gid</span>]<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">input </span><br />led-zeppelin<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">result</span><br />{<span style="color: darkslateblue;">:artist/gid</span> #uuid <span style="color: #8b2252;">"678d88b2-87b0-403b-b63d-5da7465aecc3"</span>, <br /> <span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"Led Zeppelin"</span>}</pre><br />The underscore prefix reverses the direction of an attribute, so <span style="font-family: Courier New, Courier, monospace;">:artist/_country</span> pulls all the artists for a particular country:<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">pattern</span><br />[<span style="color: darkslateblue;">:artist/_country</span>]<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">input</span><br />greatBritain<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">result</span><br />{<span style="color: darkslateblue;">:artist/_country</span> [{<span style="color: darkslateblue;">:db/id</span> 17592186045751} <br /> {<span style="color: darkslateblue;">:db/id</span> 17592186045755} <br /> ...]}</pre><h4>Components</h4><div>Datomic component attributes are pulled recursively by default, so the <span style="font-family: Courier New, Courier, monospace;">:release/media</span> pattern below automatically returns a release's tracks as well:</div><div><br /></div><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">pattern</span><br />[<span style="color: darkslateblue;">:release/media</span>]<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">input</span><br />darkSideOfTheMoon<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">result</span><br /> {<span style="color: darkslateblue;">:release/media</span><br /> [{<span style="color: darkslateblue;">:db/id</span> 17592186121277,<br /> <span style="color: darkslateblue;">:medium/format</span> {<span style="color: darkslateblue;">:db/id</span> 17592186045741},<br /> <span style="color: darkslateblue;">:medium/position</span> 1,<br /> <span style="color: darkslateblue;">:medium/trackCount</span> 10,<br /> <span style="color: darkslateblue;">:medium/tracks</span><br /> [{<span style="color: darkslateblue;">:db/id</span> 17592186121278,<br /> <span style="color: darkslateblue;">:track/duration</span> 68346,<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"Speak to Me"</span>,<br /> <span style="color: darkslateblue;">:track/position</span> 1,<br /> <span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:db/id</span> 17592186046909}]}<br /> {<span style="color: darkslateblue;">:db/id</span> 17592186121279,<br /> <span style="color: darkslateblue;">:track/duration</span> 168720,<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"Breathe"</span>,<br /> <span style="color: darkslateblue;">:track/position</span> 2,<br /> <span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:db/id</span> 17592186046909}]}<br /> {<span style="color: darkslateblue;">:db/id</span> 17592186121280,<br /> <span style="color: darkslateblue;">:track/duration</span> 230600,<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"On the Run"</span>,<br /> <span style="color: darkslateblue;">:track/position</span> 3,<br /> <span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:db/id</span> 17592186046909}]}<br /> ...]}]}</pre><h4>Map Specifications</h4>Instead of just an attribute name, you can use a nested map specification to pull related entities. &nbsp;The pattern below pulls the <span style="font-family: Courier New, Courier, monospace;">:db/id</span> and <span style="font-family: Courier New, Courier, monospace;">:artist/name</span> of each artist:<br /><div class="outline-2" id="outline-container-8" style="-webkit-text-stroke-width: 0px; color: black; font-family: Times, serif; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;"></div><br /><div class="outline-2" id="outline-container-7" style="-webkit-text-stroke-width: 0px; color: black; font-family: Times, serif; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;"><div class="outline-text-2" id="text-7"><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">pattern</span><br />[<span style="color: darkslateblue;">:track/name</span> {<span style="color: darkslateblue;">:track/artists</span> [<span style="color: darkslateblue;">:db/id</span> <span style="color: darkslateblue;">:artist/name</span>]}]<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">input</span><br />ghostRiders<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">result</span><br />{<span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:db/id</span> 17592186048186, <span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"Bob Dylan"</span>}<br /> {<span style="color: darkslateblue;">:db/id</span> 17592186049854, <span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"George Harrison"</span>}],<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"Ghost Riders in the Sky"</span>}<br /></pre></div></div><br />And of course everything nests arbitrarily, in case you need the release's medium's track's names and artists:<br /><br /><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"> <span style="color: firebrick;">;; </span><span style="color: firebrick;">pattern</span><br />[{<span style="color: darkslateblue;">:release/media</span><br /> [{<span style="color: darkslateblue;">:medium/tracks</span><br /> [<span style="color: darkslateblue;">:track/name</span> {<span style="color: darkslateblue;">:track/artists</span> [<span style="color: darkslateblue;">:artist/name</span>]}]}]}]<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">input</span><br />concertForBanglaDesh<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">result</span><br /> [{<span style="color: darkslateblue;">:medium/tracks</span><br /> [{<span style="color: darkslateblue;">:track/artists</span><br /> [{<span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"Ravi Shankar"</span>} {<span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"George Harrison"</span>}],<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"George Harrison / Ravi Shankar Introduction"</span>}<br /> {<span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"Ravi Shankar"</span>}],<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"Bangla Dhun"</span>}]}<br /> {<span style="color: darkslateblue;">:medium/tracks</span><br /> [{<span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"George Harrison"</span>}],<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"Wah-Wah"</span>}<br /> {<span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"George Harrison"</span>}],<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"My Sweet Lord"</span>}<br /> {<span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"George Harrison"</span>}],<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"Awaiting on You All"</span>}<br /> {<span style="color: darkslateblue;">:track/artists</span> [{<span style="color: darkslateblue;">:artist/name</span> <span style="color: #8b2252;">"Billy Preston"</span>}],<br /> <span style="color: darkslateblue;">:track/name</span> <span style="color: #8b2252;">"That's the Way God Planned It"</span>}]<br /> ...]}</pre><h4>Try It Out</h4><div>The Pull API has many other capabilities not shown here. &nbsp;See the <a href="http://docs.datomic.com/pull.html" target="_blank">full docs</a> for <a href="http://docs.datomic.com/pull.html#default-expressions" target="_blank">defaults</a>, <a href="http://docs.datomic.com/pull.html#limit-expressions" target="_blank">limits</a>, <a href="http://docs.datomic.com/pull.html#recursive-specifications" target="_blank">bounded and unbounded recursion</a>, and more. &nbsp;Or check out the examples in <a href="https://github.com/Datomic/day-of-datomic/blob/master/tutorial/pull.clj" target="_blank">Clojure</a> and <a href="https://github.com/Datomic/datomic-java-examples/blob/master/src/java/datomic/samples/Pull.java" target="_blank">Java</a>.</div>

  ]]>
	</description>
    </item>
    <item>
      <title>Stuff Happens: Fixing Bad Data in Datomic</title>
      <link>https://blog.datomic.com/2014/08/stuff-happens-fixing-bad-data-in-datomic.html</link>
      <pubDate>Sat, 19 Jul 2014 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2014/08/stuff-happens-fixing-bad-data-in-datomic.html</guid>
      	<description>
        <![CDATA[
	Oops! &nbsp;You just put some bad data in your system, and now you need a way to clean it up. &nbsp;In this article, we look at how to recover from data errors. &nbsp;Along the way, we will explore how Datomic models time.<br /><h2>A Motivating Example</h2><div><div>ACME Co. buys, sells, and processes things. &nbsp;Unfortunately, their circa-2003 web interface is not a shining example of UI/UX design. &nbsp;Befuddled by all the modal screens, managers regularly put bad data into the system.</div><div><br /></div><div>In fact, manager Steve just accidentally created an inventory record showing that ACME now has 999 Tribbles. &nbsp;This is ridiculous, since everyone knows that the CEO refuses to deal in Tribbles, citing "a bad experience". In a rather excited voice, Steve says "Quick, please delete the last entry added to the system!"</div><div><br /></div><div>As is so often the case, job one is to carefully interpret a stakeholder's request. &nbsp;In particular, the words "delete", "last", and "entry" all warrant careful consideration.</div></div><h3>What "Delete" Means</h3><div><div>Let's start with "delete". &nbsp;At first glance, one might think that Steve wants us to do our best to "unhappen" his mistake. But upon reflection, that isn't such a good idea. &nbsp;The database is a live system, and someone may have used the bad data to make decisions. &nbsp;If so, then simply <i>excising</i> the mistake will just lead to more confusion later. What if, during the few minutes Tribbles were in the inventory, we sold a Tribble? &nbsp;Or, more subtly, what if we moved our widget inventory to a different warehouse to make room for the nonexistent Tribbles?</div><div><br /></div><div>Databases need to remember the history of their data, even (and perhaps especially) when the data is later discovered to be bad. &nbsp;An easy analogy to drive home the point is source control. &nbsp;Source control systems act as a simple database for code. &nbsp;When a bug happens, you care very much about which versions of the code manifest the bug.</div><div><br /></div><div>So rather than deleting the Tribbles, we want something more like a "reverting commit" in source control; that is, to record that we no longer believe that we have (or in fact ever had) Tribbles, but that during a specific time window we mistakenly believed we had 999 Tribbles.</div></div><h3>What "Last" Means</h3><div><div>Next, let us consider the temporal word "last". &nbsp;Happily, ACID databases have a unit of time ordering: transactions. Datomic goes a step further with&nbsp;<i>reified transactions</i>, i.e. transactions that you can manipulate as first-class objects in the system. &nbsp;In such a system, you might indeed be able to say "Treat the last transaction as a data entry error and record a reverting transaction."</div><div><br /></div><div>We still need to be careful, though, about what we mean by "last". &nbsp;Again, the inventory system is a live system, so the last transaction is a moving target. &nbsp;It would be dangerous and incorrect to blindly revert the last transaction, without making sure that Steve's erroneous transaction is still the last one. Generally, we will want a way to review recent transactions, and then narrow down by some other criteria, e.g. the id for Tribbles.</div></div><h3>What "Entry" Means</h3><div><div>Finally, let's consider what constitutes an "entry". &nbsp;This is a domain concept, and might or might not correspond directly to a row in a table, or to a document, or whatever metaphor your database encourages. &nbsp;Mistakes can have arbitrary and irregular shapes. &nbsp;When correcting errors, we will want to have <i>granular</i> representations of data, so that we can precisely target the error without also having to modify correct data nearby.</div><div><br /></div><div>Putting that all together, we need to:</div><div><ul><li>locate the precise problem among recent transaction data</li><li>create a transaction that reverts the bad information...</li><li>...without forgetting that the problem happened. &nbsp;</li></ul></div><div>Let's take this to code.</div></div><h2>Retraction in Code</h2><div><div>The code examples that follow are in Groovy rather than Java for concision's sake. &nbsp;You can download the <a href="https://github.com/Datomic/datomic-groovy-examples/blob/1a5eccf0840f804d2a002a869f3b0b7ae96b7691/src/main/CorrectingErrors.groovy" target="_blank">sample code</a> from the <a href="https://github.com/Datomic/datomic-groovy-examples" target="_blank">Datomic Groovy Examples</a> repository.</div><div><br /></div><div>Let's begin with our erroneous transaction, creating a record for Tribbles with a unique id, description, and count:</div></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">addTribbles = [[<span style="color: #8b2252;">':db/id'</span>: tempid(<span style="color: #8b2252;">':db.part/user'</span>),<br /> <span style="color: #8b2252;">':item/id'</span>: <span style="color: #8b2252;">'0042-TRBL'</span>,<br /> <span style="color: #8b2252;">':item/description'</span>: <span style="color: #8b2252;">'Tribble: a low maintenance pet.'</span>,<br /> <span style="color: #8b2252;">':item/count'</span>: 999]];<br />conn.transact(addTribbles).get();</pre></div><h3>Finding the Problem</h3><div><div>OK, the clock is ticking: we have bad data in the system. &nbsp;How can we look to see what we have? &nbsp;For many everyday uses, you want an associative (entity) view of data. &nbsp;Depending on your language and tools, an entity representation may be a strongly-typed object or a mere dictionary, and may be generated by hand or automated through an ORM. &nbsp;Regardless, an associative representation allows you to navigate from keys to values.</div><div><br /></div><div>In Datomic, you can pass a <a href="http://docs.datomic.com/identity.html#lookup-refs" target="_blank">lookup ref</a> (a pair containing a unique key and its value) to the&nbsp;<a href="http://docs.datomic.com/entities.html" target="_blank">entity API</a> to get an entity:</div></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">db = conn.db();<br />db.entity([<span style="color: #8b2252;">':item/id'</span>, <span style="color: #8b2252;">'0042-TRBL'</span>]);</pre></div><div>Entities imply a three way relation of entity / attribute / value. &nbsp;The entity is implicit in object identity, the attributes are keys (or getter methods), and the values are looked up via the attributes. Given an entity, you can call <a href="http://docs.datomic.com/javadoc/datomic/Entity.html#keySet()" target="_blank">keySet</a> to find its keys, or <a href="http://docs.datomic.com/javadoc/datomic/Entity.html#get(java.lang.Object)" target="_blank">get</a> to lookup the value at a particular key.</div><div><div><br /></div><div>What entities do <i>not</i> tell you is how, when, or why data got into the system. &nbsp;One way to improve this is to think in terms of a broader relation. &nbsp;Instead of a 3-tuple of entity / attribute / value, Datomic uses a <i>datom</i>: a 5-tuple of entity / attribute / value / transaction / added. &nbsp;The fourth slot, <i>transaction</i>, references an entity that records the time the transaction was added to the system (plus possibly other facts about the transaction). &nbsp;The fifth slot, <i>added</i>, is a boolean that records whether the datom is being asserted (true) or retracted (false).</div><div><br /></div><div>Datoms allow you to see (and annotate) the complete history of entities in your system. &nbsp;For example, the following Datalog query will return all the facts about Tribbles.</div></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">q(<span style="color: #8b2252;">'''[:find ?aname ?v ?tx ?added</span><br /><span style="color: #8b2252;"> :in $ ?e</span><br /><span style="color: #8b2252;"> :where [?e ?a ?v ?tx ?added]</span><br /><span style="color: #8b2252;"> [?a :db/ident ?aname]]'''</span>,<br /> db,<br /> [<span style="color: #8b2252;">':item/id'</span>, <span style="color: #8b2252;">'0042-TRBL'</span>]);</pre></div><div>We aren't going to cover Datalog syntax here, but will point out a few things in passing:</div><div><div><ul><li>variables begin with <b><span style="font-family: Courier New, Courier, monospace;">?</span></b></li><li>data patterns in the <span style="font-family: Courier New, Courier, monospace;"><b>:where</b></span> clause are specified in Datom order, i.e. entity, attribute, value, transaction, added</li><li>the <span style="font-family: Courier New, Courier, monospace;"><b>:in</b></span> clause binds parameters, so this query binds <b><span style="font-family: Courier New, Courier, monospace;">?e</span></b> to find only facts about id&nbsp;<span style="background-color: #f3f5f7; color: #8b2252; font-family: courier, monospace; font-size: 14px;">0042-TRBL</span>, Tribbles.</li></ul></div><div>The query results, shown below, show us that all facts about Tribbles were added in the same transaction, 13194139534315.</div><div><br /></div><div id="content" style="font-family: Times, serif; font-size: 16px;"><div class="outline-2" id="outline-container-8"><div class="outline-text-2" id="text-8"><table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups" style="border-collapse: collapse; color: black; font-size: 16px;"><caption></caption><colgroup><col class="left" style="margin-left: 0px; margin-right: auto;"></col><col class="left" style="margin-left: 0px; margin-right: auto;"></col><col class="right" style="margin-left: auto; margin-right: 0px; text-align: right;"></col><col class="left" style="margin-left: 0px; margin-right: auto;"></col></colgroup><thead><tr><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Attribute</th><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Value</th><th class="right" scope="col" style="margin-left: auto; margin-right: 0px; text-align: center; vertical-align: top;">Transaction</th><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Added?</th></tr></thead><tbody><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/description</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">Tribble: a low maintenance pet.</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/id</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">0042-TRBL</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/count</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">999</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr></tbody></table></div></div></div></div><h3>Searching The Log</h3><div><div>In the query above, we knew that the problem was Tribbles, and could use that to look up the information. &nbsp;Let's imagine instead that we know only that the problem just happened. To ask a "when" question, you can explicitly access the <a href="http://docs.datomic.com/log.html" target="_blank">database log</a>, which is a time index. In Datomic, the <i>basisT</i> of a database identifies the most recent transaction, and can be passed to the <b><span style="font-family: Courier New, Courier, monospace;">tx-data</span></b> function inside a query to access the log and return datoms from a specific transaction. The following query shows the entire transaction that added the Tribbles.</div></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">log = conn.log();<br />q(<span style="color: #8b2252;">'''[:find ?e ?aname ?v ?tx ?added</span><br /><span style="color: #8b2252;"> :in $ ?log ?tx</span><br /><span style="color: #8b2252;"> :where [(tx-data ?log ?tx) [[?e ?a ?v _ ?added]]]</span><br /><span style="color: #8b2252;"> [?a :db/ident ?aname]]'''</span>,<br /> db,<br /> log,<br /> db.basisT());</pre></div><div>This query shows us not only the troubled Tribble datoms, but also information about the transaction that added them:</div><div><br /></div><div><table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups" style="border-collapse: collapse; color: black; font-family: Times, serif; font-size: 16px;"><caption></caption><colgroup><col class="right" style="margin-left: auto; margin-right: 0px; text-align: right;"></col><col class="left" style="margin-left: 0px; margin-right: auto;"></col><col class="left" style="margin-left: 0px; margin-right: auto;"></col><col class="right" style="margin-left: auto; margin-right: 0px; text-align: right;"></col><col class="left" style="margin-left: 0px; margin-right: auto;"></col></colgroup><thead><tr><th class="right" scope="col" style="margin-left: auto; margin-right: 0px; text-align: center; vertical-align: top;">Entity</th><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Attribute</th><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Value</th><th class="right" scope="col" style="margin-left: auto; margin-right: 0px; text-align: center; vertical-align: top;">Transaction</th><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Added?</th></tr></thead><tbody><tr><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">17592186045420</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/description</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">Tribble: a low maintenance pet.</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">17592186045420</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/id</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">0042-TRBL</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">17592186045420</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/count</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">999</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:db/txInstant</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">2014-05-19T17:20:48.200-00:00</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr></tbody></table></div><div><br /></div><div><div>The combination of granular datoms, the powerful Datalog query language, and direct access to the database log make it possible to find out everything about a data error. &nbsp;Now let's fix the error, without losing history of the event.</div></div><h2>Fixing the Problem</h2><div><div>The transaction that added the Tribbles actually said three things about Tribbles:</div><div><ul><li>Tribbles exist</li><li>Tribbles have a description</li><li>we have 999 Tribbles &nbsp;</li></ul></div><h3>Simple Retraction</h3><div>Let's presume that it is innocuous to acknowledge the existence of Tribbles. &nbsp;Thus we can make a very granular correction, refuting only the absurd notion that we have Tribbles in inventory:</div></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">errDoc = <span style="color: #8b2252;">'Error correction entry. We do not sell Tribbles.'</span>;<br />weDontSellTribbles = <br />[[<span style="color: #8b2252;">':db/add'</span>, [<span style="color: #8b2252;">':item/id'</span>, <span style="color: #8b2252;">'0042-TRBL'</span>], <span style="color: #8b2252;">':item/count'</span>, 0],<br /> [<span style="color: #8b2252;">':db/add'</span>, tempid(<span style="color: #8b2252;">':db.part/tx'</span>), <span style="color: #8b2252;">':db/doc'</span>, errDoc]];<br />conn.transact(weDontSellTribbles).get();</pre></div><div>This correction adds two facts to the database:</div><div><div><ol><li>an assertion that we have, in fact, zero Tribbles</li><li>a documentation string on the transaction entity (<span style="font-family: Courier New, Courier, monospace;">:db.part/tx</span>) explaining the correction</li></ol></div><h3>Retraction with Provenance</h3><div>Another possibility is that ACME does not want even to acknowledge the existence of Tribbles. &nbsp;So we need to retract the entire Tribble entity. &nbsp;Also, ACME has a policy of recording a manager's identity along with an error correction. Here, then is a transaction that removes the Tribble entity entirely, and credits John Doe with the removal:</div></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">retractTribbles = <br />[[<span style="color: #8b2252;">':db.fn/retractEntity'</span>, [<span style="color: #8b2252;">':item/id'</span>, <span style="color: #8b2252;">'0042-TRBL'</span>]],<br /> [<span style="color: #8b2252;">':db/add'</span>, <br /> tempid(<span style="color: #8b2252;">':db.part/tx'</span>), <br /> <span style="color: #8b2252;">':corrected/by'</span>, [<span style="color: #8b2252;">':manager/email'</span>, <span style="color: #8b2252;">'jdoe@example.com'</span>]]];<br />conn.transact(retractTribbles).get();</pre></div><div><span style="font-family: Courier New, Courier, monospace;">:db.fn/retractEntity</span> is a built-in database function that expands to datoms retracting every fact about an entity. &nbsp;<span style="font-family: Courier New, Courier, monospace;">:correction/by</span> is an attribute specific to the <a href="https://github.com/Datomic/datomic-groovy-examples/blob/1a5eccf0840f804d2a002a869f3b0b7ae96b7691/resources/main/inventory.edn" target="_blank">schema of this database</a>, and is an example of how you can extend the information model to capture provenance information for transactions.</div><div><h3>You <i>Can</i> Go Back Again</h3><div>Now that Tribbles have been retracted entirely, they will be invisible to queries or entity calls against the database. &nbsp;But while they are gone, they are not forgotten. &nbsp;The history view of a database shows not just the present, but the entire past of the database. &nbsp;The following query shows the complete history of Tribbles in the database:</div></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">hist = conn.db().history();<br />q(<span style="color: #8b2252;">'''[:find ?aname ?v ?tx ?added</span><br /><span style="color: #8b2252;"> :in $ ?e</span><br /><span style="color: #8b2252;"> :where [?e ?a ?v ?tx ?added]</span><br /><span style="color: #8b2252;"> [?a :db/ident ?aname]]'''</span>,<br /> hist,<br /> [<span style="color: #8b2252;">':item/id'</span>, <span style="color: #8b2252;">'0042-TRBL'</span>]);</pre></div><div>As you can see below, this history includes the original problem transaction, the partial correction, and the complete removal of the entity.</div><div><div><br /><table border="2" cellpadding="6" cellspacing="0" frame="hsides" rules="groups" style="border-collapse: collapse; color: black; font-family: Times, serif; font-size: 16px;"><caption></caption><colgroup><col class="left" style="margin-left: 0px; margin-right: auto;"></col><col class="left" style="margin-left: 0px; margin-right: auto;"></col><col class="right" style="margin-left: auto; margin-right: 0px; text-align: right;"></col><col class="left" style="margin-left: 0px; margin-right: auto;"></col></colgroup><thead><tr><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Attribute</th><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Value</th><th class="right" scope="col" style="margin-left: auto; margin-right: 0px; text-align: center; vertical-align: top;">Transaction</th><th class="left" scope="col" style="margin-left: 0px; margin-right: auto; text-align: center; vertical-align: top;">Added?</th></tr></thead><tbody><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/description</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">Tribble: a low maintenance pet.</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/id</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">0042-TRBL</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/count</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">999</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534315</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/count</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">999</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534317</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">false</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/count</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">0</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534317</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">true</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/id</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">0042-TRBL</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534318</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">false</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/description</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">Tribble: a low maintenance pet.</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534318</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">false</td></tr><tr><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">:item/count</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">0</td><td class="right" style="margin-left: auto; margin-right: 0px; text-align: right; vertical-align: top;">13194139534318</td><td class="left" style="margin-left: 0px; margin-right: auto; vertical-align: top;">false</td></tr></tbody></table></div></div><div><h3>Where Are We?</h3><div>We have now accomplished everything we set out to do:</div><div><ul><li>We used Datalog queries to precisely locate problem data, both by recency and by identifying key.</li><li>We took advantage of the granularity of datoms to create transactions that precisely retracted problem data.</li><li>We used reified transactions and the history view of the database to remember what went wrong, and how it was fixed.</li></ul></div><div>Time is a fundamental dimension of information systems, and it cannot be easily retrofitted to systems that only support traditional row or document views of information. &nbsp;In particular, note that the queries above take a database (not a connection) argument. &nbsp;That database can be filtered with&nbsp;<a href="http://docs.datomic.com/javadoc/datomic/Database.html#history()" target="_blank">history</a>,&nbsp;<a href="http://docs.datomic.com/javadoc/datomic/Database.html#asOf(java.lang.Object)" target="_blank">asOf</a>, or</div><div><a href="http://docs.datomic.com/javadoc/datomic/Database.html#since(java.lang.Object)" target="_blank">since</a>&nbsp;to pass different windows of time to the same query. &nbsp;With a time model, "point-in-time" or "range-of-time" queries can use the same logic as "now" queries.</div><div><br /></div><div>That all sounds pretty good. &nbsp;So, should all of your information systems build upon a time model?</div></div><h2>Modeling Time: Concerns and Tradeoffs</h2><div><div>There are a number of issues to consider when modeling time in an information system; we will consider a few of the most common issues here.</div><div><ol><li>What are the performance concerns when keeping historical data?</li><li>Is there some data for which historical information is irrelevant or counterproductive?</li><li>But I <i>really</i> want to delete something!</li><li>I understand the importance of remembering past mistakes, but I want "clean" history, too.</li></ol></div></div><h3>Performance Concerns</h3><div><div>Data structures that preserve past values of themselves are called <i>persistent. </i>&nbsp;A common first reaction to persistence in databases is "Can I actually afford to remember everything?" &nbsp;You may remember that a similar objection was raised when Git first became popular: "Can I really afford to keep the entire history of projects on my laptop?"</div><div><br /></div><div>It is important to understand that history can be managed so that queries are "pay as you go". &nbsp;If you do not use history in a particular query, that query will perform just as well as if you were not storing history. &nbsp;Modern immutable databases such as Datomic make such optimizations.</div><div><br /></div><div>With that out of the way, the other major concern is storage cost. For many systems, particularly transactional systems of record, the balance of this argument is usually in favor of keeping everything. If the information is worth recording at all, it is worth the cost of keeping it.</div><div><br /></div><div>But some information has little value, and does not warrant history.</div></div><h3>Not Everything Needs History</h3><div><div>At the other extreme from systems of record you have high-volume data that has little information value per fact, but some utility in the aggregate. &nbsp;A good example of this is a hit counter on web site. &nbsp;While you might be interested to know that 10,000 people are visiting every hour, you probably don't care to know the exact time for each counter increment.</div><div><br /></div><div>Counters and other high churn, low point-in-time value storage does not benefit from history.&nbsp;</div></div><h3>Excision</h3><div><div>There are a few scenarios where systems really do need to deliberately and irrevocably lose data. &nbsp;The most common such scenario is a legal requirement to remove information from a system for privacy or intellectual property reasons.</div><div><br /></div><div>For such situations, Datomic provides&nbsp;<i><a href="http://docs.datomic.com/excision.html" target="_blank">excision</a></i>, which permanently removes facts from the system. This feature should <i>never</i> be used to fix mistakes. &nbsp;To continue the source code analogy, this would be the equivalent of saying "Wow, that was a really dodgy bug, let's corrupt source control so it looks like the bug never happened."</div></div><h3>Clean History</h3><div><div>We have been talking about history as "what we believed in the past". But from there one might aspire to know "what was <i>true</i> in the past", or at least "what we <i>now</i> think was true at some point of time in the past.</div><div><br /></div><div>The ability to annotate transactions provides a path to multiple notions of history. For example, you could define a <span style="font-family: Courier New, Courier, monospace;">:tx/mistake</span> attribute, and use it to mark transactions that later prove to be erroneous. &nbsp;You could then query against a <a href="http://docs.datomic.com/javadoc/datomic/Database.html#filter(datomic.Database.Predicate)" target="_blank">filtered</a>&nbsp;database that does not see those transactions at all.</div></div><h2>Wrapping Up</h2><div><div>Stuff happens, and information systems will acquire bad data. &nbsp;<i>Never delete your mistakes</i>. &nbsp;Use fine grained information such as datoms to pinpoint your errors, and use retraction and reified transactions in a persistent database such as Datomic to correct errors while preserving history.</div></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Adaptive Indexing</title>
      <link>https://blog.datomic.com/2014/03/datomic-adaptive-indexing.html</link>
      <pubDate>Mon, 24 Feb 2014 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2014/03/datomic-adaptive-indexing.html</guid>
      	<description>
        <![CDATA[
	We are pleased to announce today new <b>Adaptive Indexing</b> support for <a href="http://datomic.com/">Datomic</a>. Adaptive indexing involves both a new index format and algorithm for how indexes are maintained. It should prove especially beneficial to those with large databases, high write loads, or large imports.<br /><h4>Some of the benefits:</h4><ul><li>Reduced work to be done per indexing job</li></ul><div>There will be fewer index segments written, which should take less time and/or allow for reduced write provisioning when using DynamoDB.</div><div><br /></div><div><ul><li>Reduced memory requirements</li></ul><div>We have revised downwards both the default and recommended thresholds for memory-index-threshold (to 32m) and memory-index-max (to 512m), for all workloads. This will also reduce memory pressure on peers, which are similarly configured. In addition, indexing itself uses less memory and has better GC characteristics. You will not approach memory-index-max except during imports and bulk loads.</div></div><div><br /></div><div><ul><li>Simpler configuration and less variability</li></ul><div>You should rarely need to diverge from the defaults, and generally can use the same configuration for imports and ongoing production.</div></div><div><br /></div><div><ul><li>Sustainable import rates independent of db size</li></ul><div>You will see indexing job times flatten out even as your db size grows linearly, as there is a sub-linear worst-case relationship between db size and indexing job size All of this is done while minimizing the amount of merging done during reads.</div></div><div><br /></div><div><b>TL;DR - much better and more predictable performance, using fewer resources.</b></div><div><br /></div><div>We expect adaptive indexing to make a tangible difference to most customers, and look forward to your feedback. Be sure to read the <a href="http://docs.datomic.com/release-notices.html#adaptive-indexing">release notices</a> for important details.</div><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Lookup Refs</title>
      <link>https://blog.datomic.com/2014/02/datomic-lookup-refs.html</link>
      <pubDate>Mon, 13 Jan 2014 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2014/02/datomic-lookup-refs.html</guid>
      	<description>
        <![CDATA[
	<a href="http://datomic.com/" target="_blank">Datomic</a>'s new <a href="http://docs.datomic.com/identity.html#lookup-refs">lookup refs</a> provide an easy way to identify entities by domain unique identifiers.<br /><div><h3>Rationale</h3><div>Datomic supports several approaches to <a href="http://docs.datomic.com/identity.html" target="_blank">identity</a>, including internal identifiers (entity IDs that are unique within a database) and external identifiers (domain attributes that are designated to be <span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>:db.unique/identity</b></span>). &nbsp;Lookup refs provide a concise data representation that accords to external ids the powers of internal ids, and can be used interchangeably with internal ids in the Datomic API. This is powerful, since often, e.g. in the front-end of a system or during imports, you already have the external ids in hand. With lookups refs you can often avoid having to incorporate a lookup in application code since the lookup will be done implicitly when resolving the lookup ref (thus the name).</div><h3>Implementation</h3><div>A <b>lookup ref</b> is simply a java.util.List containing two elements: a unique attribute and a value for that attribute. &nbsp;Encoded in <a href="http://edn-format.org/" target="_blank">edn</a>, a Lookup ref looks like this:</div></div><div><br /></div><div><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">[<span style="color: darkslateblue;">:org/email</span> <span style="color: #8b2252;">"info@datomic.com"</span>]</pre></div><div><br /></div><div><div>Lookup refs can be used in the <a href="http://docs.datomic.com/javadoc/datomic/Entity.html" target="_blank">entity API</a>, or in any of the database&nbsp;<a href="http://docs.datomic.com/javadoc/datomic/Database.html" target="_blank">index APIs</a>. &nbsp;For example, the following code retrieves an entity:</div><div><br /></div></div><div><pre class="src src-java" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">// </span><span style="color: firebrick;">Groovy</span><br />db.entity([<span style="color: #8b2252;">':org/email'</span>, <span style="color: #8b2252;">'info@datomic.com'</span>])</pre></div><div><div><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">Clojure</span><br /><span style="color: #8c8c8c;">(</span>d/entity db [<span style="color: darkslateblue;">:org/email</span> <span style="color: #8b2252;">"info@datomic.com"</span>]<span style="color: #8c8c8c;">)</span></pre></div><div><br /></div><div>Lookup refs can also be used to refer to existing entities in transaction data. &nbsp;This allows updating transactions to specify <span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><b>:db/id</b></span> directly instead of using a dummy upsert, as shown below:</div><div><br /></div></div><div><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">;; </span><span style="color: firebrick;">edn transaction data, using temp :db/id and dummy upsert</span><br />[{<span style="color: darkslateblue;">:db/id</span> #db/id[<span style="color: darkslateblue;">:db.part/user</span>]<br /> <span style="color: darkslateblue;">:org/email</span> <span style="color: #8b2252;">"info@datomic.com"</span>,<br /> <span style="color: darkslateblue;">:org/favoriteColor</span> <span style="color: darkslateblue;">:blue</span>}]<br /><br /><span style="color: firebrick;">;; </span><span style="color: firebrick;">edn transaction data, using lookup ref</span><br />[{<span style="color: darkslateblue;">:db/id</span> [<span style="color: darkslateblue;">:org/email</span> <span style="color: #8b2252;">"info@datomic.com"</span>],<br /> <span style="color: darkslateblue;">:org/favoriteColor</span> <span style="color: darkslateblue;">:blue</span>}]</pre></div><div><div><br /></div><div>Similarly, they can be used in transactions to build ref relationships.<br /><br />We expect that <b>lookup refs</b> will expedite a wide variety of use cases, including imports, interactive exploration, and client application development. &nbsp;<br /><br />We look forward to your feedback.</div></div><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Schema Alteration</title>
      <link>https://blog.datomic.com/2014/01/schema-alteration.html</link>
      <pubDate>Mon, 23 Dec 2013 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2014/01/schema-alteration.html</guid>
      	<description>
        <![CDATA[
	<a href="http://datomic.com/">Datomic</a>&nbsp;is a database that has flexible, minimal schema. Starting with version 0.9.4470, available <a href="http://www.datomic.com/get-datomic.html">here</a>, we have added the ability to alter existing schema attributes after they are first defined. You can alter schema to<br /><br /><ul><li>rename attributes</li><li>rename your own programmatic identities (uses of <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace; font-size: x-small;"><b>:db/ident)</b></span></li><li>add or remove indexes&nbsp;</li><li>add or remove uniqueness constraints</li><li>change attribute cardinality</li><li>change whether history is retained for an attribute</li><li>change whether an attribute is treated as a component</li></ul><br />Schema alterations use the same transaction API as all other transactions, just as schema installation does. &nbsp;All schema alterations can be performed while a database is online, without requiring database downtime. &nbsp;Most schema changes are effective immediately, at the end of the transaction. &nbsp;There is one exception: adding an index requires a background job to build the new index. You can use the new&nbsp;<a href="https://docs.datomic.com/on-prem/javadoc/datomic/Connection.html#syncSchema-long-">syncSchema API</a> for detecting when a schema change is available.<br /><br />When renaming an attribute or identity, you can continue to use the old name as long as you haven't repurposed it. This allows for incremental application updating.<br /><br /><div>See the schema alteration <a href="https://docs.datomic.com/on-prem/schema/schema.html#schema-alteration">docs</a> for the details. <br /><br />Schema alteration has been our most requested enhancement. We hope you find it useful and look forward to your feedback.<br /><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic 2013 Recap</title>
      <link>https://blog.datomic.com/2014/01/datomic-2013-recap.html</link>
      <pubDate>Sun, 8 Dec 2013 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2014/01/datomic-2013-recap.html</guid>
      	<description>
        <![CDATA[
	2013 was a great year for <a href="http://datomic.com/" target="_blank">Datomic</a>. &nbsp;The value of a flexible information model and immutable data have proven themselves time and again. &nbsp;Customers have built a variety of powerful systems, taking advantage of<br /><div><ul><li><a href="http://docs.datomic.com/acid.html" target="_blank">ACID</a> transactions</li><li>pluggable SQL/NoSQL/cloud storage</li><li>complete access to the history of information</li><li>the Datalog <a href="http://docs.datomic.com/query.html" target="_blank">query language</a></li><li>elastic read scalability</li><li>a granular information model</li></ul></div><div><div>Over the course of the year, we produced over 40 Datomic releases. The API has been remarkably stable: Our commitment to a strong architecture has allowed us to focus on adding features and fleshing out the vision, without the churn of revisiting past decisions. &nbsp;</div><div><br /></div><div>A major new feature is the <a href="http://blog.datomic.com/2013/10/datomic-console.html" target="_blank">Datomic Console</a>, a graphical UI for exploring Datomic databases. &nbsp;The console provides a great visual introduction to the Datomic information model. &nbsp;It supports exploring schema, building and executing queries, navigating entities, examining transaction history, and walking raw indexes.&nbsp;</div><div><br /></div><div>We made several API additions:</div></div><div><div><ul><li><a href="http://blog.datomic.com/2013/05/excision.html" target="_blank">Excision</a>, a sound model (and API) for permanent removal of data, with auditability.</li><li>The <a href="http://docs.datomic.com/log.html" target="_blank">log</a> API provides the ability to access the log, which is more properly viewed as a time index.</li><li>The <a href="http://docs.datomic.com/javadoc/datomic/Database.html#seekDatoms(java.lang.Object, java.lang.Object...)" target="_blank">seekDatoms</a> and <a href="http://docs.datomic.com/javadoc/datomic/Database.html#entidAt(java.lang.Object, java.lang.Object)" target="_blank">entidAt</a> APIs provide advanced capability for accessing Datomic's indexes, augmenting the datoms API.</li><li>The <a href="http://blog.datomic.com/2013/06/sync.html" target="_blank">sync</a> API allows multiple processes to coordinate around points in time-of-record, or relative to local process time.</li><li>Transaction <a href="http://blog.datomic.com/2013/06/component-entities.html" target="_blank">map expansion</a> automates the creation of arbitrarily nested data.</li></ul></div></div><div>We also made a number of operational improvements:</div><div><ul><li>We added <a href="http://blog.datomic.com/2013/12/cassandra-support.html" target="_blank">Cassandra</a> and to the list of supported storage, in addition to the existing options of DynamoDB, SQL, filesystem, CouchBase, Infinispan, and Riak.</li><li>The <a href="http://blog.datomic.com/2013/11/datomic-pro-starter-edition.html" target="_blank">Starter Edition</a> of the Datomic Pro license makes all storages available, for free.</li><li>We have added a number of new <a href="http://docs.datomic.com/monitoring.html" target="_blank">CloudWatch metrics</a>, and a pluggable metrics API for integration with other systems.</li><li>The <a href="http://blog.datomic.com/2013/07/datomic-musicbrainz-sample-database.html" target="_blank">MusicBrainz sample database</a> is a great dataset for exploring Datomic.</li><li>We continue to track AWS best practices, now supporting <a href="http://blog.datomic.com/2013/11/using-iam-roles-with-datomic-on-aws.html" target="_blank">IAM roles</a> for distributing credentials and&nbsp;DynamoDB local&nbsp;for testing.</li></ul><div>We are looking forward to an equally exciting 2014. We will be delivering a number of new features requested by users, plus a few big surprises. <br /><br />Many thanks to our customers and early adopters for your support and feedback.<br /><br />Happy New Year!</div></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Cassandra Support</title>
      <link>https://blog.datomic.com/2013/12/cassandra-support.html</link>
      <pubDate>Mon, 18 Nov 2013 00:00:00 +0100</pubDate>
      <guid isPermaLink="false">2013/12/cassandra-support.html</guid>
      	<description>
        <![CDATA[
	We are pleased to announce alpha support for Cassandra as a storage service for <a href="http://datomic.com/">Datomic</a>, now available in version 0.9.4384.<br /><br />Cassandra is an elastically scalable, distributed, redundant and highly-available column store. Recent versions of Cassandra added support for compare-and-swap operations via lightweight<br />transactions using an implementation of the Paxos protocol. Datomic leverages this mechanism to manage a small number of keys per database that require coordinated access, while the bulk of a database's content is written as immutable data to a quorum of replicas in the cluster.<br /><br />Cassandra support requires a minimum Apache Cassandra 2.0.2 or newer, or equivalent. Native CQL protocol support must be enabled. Cross-data center deployments are not supported. Cassandra internal security is supported, but optional.<br /><br />This release represents preliminary support based on requests from users. We are very interested in feedback.<br /><br />For instructions on configuring Cassandra for use with Datomic, see <a href="http://docs.datomic.com/storage.html">Setting Up Storage Services</a>.<br /><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Using IAM Roles with Datomic on AWS</title>
      <link>https://blog.datomic.com/2013/11/using-iam-roles-with-datomic-on-aws.html</link>
      <pubDate>Fri, 25 Oct 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/11/using-iam-roles-with-datomic-on-aws.html</guid>
      	<description>
        <![CDATA[
	With today's <a href="http://datomic.com/" target="_blank">Datomic</a> release, you can use <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html" target="_blank">IAM</a> roles to manage permissions when running in AWS.<br /><h3>Motivation</h3>Datomic's AWS support has been designed according to the <a href="http://en.wikipedia.org/wiki/Principle_of_least_privilege" target="_blank">principle of least privilege</a>. &nbsp;When running in AWS, a Datomic transactor or peer needs only the minimum permissions necessary to communicate with various AWS services. &nbsp;These permissions are documented in <a href="http://staging.docs.datomic.com/storage.html" target="_blank">Setting Up Storage Services</a>.<br /><br />But you still need some way to <i>install</i> these minimal permissions on ephemeral virtual hardware. Early versions of AWS left this problem to the developer. &nbsp;Solutions were tedious and ad hoc, but more important they were risky. &nbsp;Leaving every application developer the task of <i>passing</i> credentials around is a recipe for credentials <i>lying</i> around in a hundred different places (or even checked into source code repositories.)<br /><br />IAM roles provide a generic solution to this problem. &nbsp;From the <a href="http://aws.amazon.com/iam/faqs/#iam_role_management_anchor" target="_blank">FAQ</a>: "An IAM role allows you to delegate access, with defined permissions, to trusted entities <i>without having to share long term access keys</i>"&nbsp;<i>&nbsp;</i>(emphasis added). &nbsp;From a developer perspective, IAM roles get credentials out of your application code.<br /><h3>Implementation</h3><div>Starting with version 0.9.4314, Datomic supports IAM roles as the default mechanism for conveying credentials in AWS. &nbsp;What does this mean for developers?</div><div><ol><li>If you are configuring Datomic for the first time, the <a href="http://staging.docs.datomic.com/storage.html" target="_blank">setup instructions</a> will secure peers and transactors using IAM roles.&nbsp;</li><li>If you have an existing Datomic installation and want to upgrade to roles, <a href="http://staging.docs.datomic.com/migrate-to-roles.html" target="_blank">Migrating to IAM Roles</a> will walk you through the process.</li><li>Using explicit credentials in transactor properties and in connection URIs is deprecated, but will continue to work. &nbsp;<i>Your existing deployments will not break.</i></li></ol><div>IAM roles make your application both easier to manage and more secure. &nbsp;Use them.</div></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Pro Starter Edition</title>
      <link>https://blog.datomic.com/2013/11/datomic-pro-starter-edition.html</link>
      <pubDate>Tue, 8 Oct 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/11/datomic-pro-starter-edition.html</guid>
      	<description>
        <![CDATA[
	<span style="font-family: Arial, Helvetica, sans-serif;">We are happy to announce today the release of&nbsp;</span><b style="font-family: Arial, Helvetica, sans-serif;">Datomic Pro Starter Edition, </b><span style="font-family: Arial, Helvetica, sans-serif;">enabling the use of <a href="http://www.datomic.com/" target="_blank">Datomic</a>&nbsp;for&nbsp;</span><span style="font-family: Arial, Helvetica, sans-serif;">small production deployments <i><b>at no cost</b></i></span><span style="font-family: Arial, Helvetica, sans-serif;">.</span><br /><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span><span style="font-family: Arial, Helvetica, sans-serif;">Datomic Pro Starter Edition features most benefits of Datomic Pro:</span><br /><ul><li><span style="font-family: Arial, Helvetica, sans-serif;">Support for <b>all storages</b></span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">A perpetual license with 12 months of updates included</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">Support for the full Datomic programming model</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;"><a href="http://blog.datomic.com/2013/10/datomic-console.html">Datomic Console</a> included with download</span></li></ul><ul></ul><div><span style="font-family: Arial, Helvetica, sans-serif;">Datomic Pro Starter Edition features community support, and does not include:</span></div><div><ul><li><span style="font-family: Arial, Helvetica, sans-serif;">High Availability transactor support</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">Integrated memcached</span></li><li><span style="font-family: Arial, Helvetica, sans-serif;">Running more than 3 processes (2 peers&nbsp;+ transactor)</span></li></ul><div><span style="font-family: Arial, Helvetica, sans-serif;">To get started, register and download&nbsp;<a href="https://my.datomic.com/starter" target="_blank">Datomic Pro Starter Edition</a>.&nbsp;</span></div></div><div><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div><div><span style="font-family: Arial, Helvetica, sans-serif;">Datomic Pro Starter Edition lets your team build a fully operational system and deploy to production with no additional steps or costs.</span></div><br />

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Console</title>
      <link>https://blog.datomic.com/2013/10/datomic-console.html</link>
      <pubDate>Sun, 29 Sep 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/10/datomic-console.html</guid>
      	<description>
        <![CDATA[
	[<b>Update: </b>Watch the <a href="https://www.youtube.com/watch?v=jyuBnl0XQ6s" target="_blank">intro video</a>.]<br /><br />The Datomic Console&nbsp;is a graphical UI for exploring <a href="http://datomic.com/" target="_blank">Datomic</a> databases.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-uAPGoXiZKlE/UmkRQBdnNOI/AAAAAAAAAGU/qf43oTJk9IE/s1600/console-window.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="328" src="/images/blog/-uAPGoXiZKlE/UmkRQBdnNOI/AAAAAAAAAGU/qf43oTJk9IE/s640/console-window.png" width="640" /></a></div><br /><br />It supports exploring schema, building and executing queries, navigating entities, examining transaction history, and walking raw indexes. &nbsp;The Datomic Console is included in <a href="http://downloads.datomic.com/pro.html" target="_blank">Datomic Pro</a>, and is available as a <a href="https://my.datomic.com/downloads/console" target="_blank">separate download</a> for Datomic Free users.<br /><h3>Exploring Schema</h3><div>The upper left corner of the console displays a tree view of the attributes defined for the current database.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-eKlDbaQTvZg/UmkRG5HRBGI/AAAAAAAAAGM/zjR9fnld5OM/s1600/console-schema.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="/images/blog/-eKlDbaQTvZg/UmkRG5HRBGI/AAAAAAAAAGM/zjR9fnld5OM/s320/console-schema.png" width="304" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div><br /></div><h3>Query</h3><div>The Query tab provides two synchronized views of queries: a graphical builder, and the equivalent textual representation.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><div><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-jx-ZmKw6o6M/UmkRa0anJzI/AAAAAAAAAGc/X9y81NzL5gE/s1600/console-query.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="/images/blog/-jx-ZmKw6o6M/UmkRa0anJzI/AAAAAAAAAGc/X9y81NzL5gE/s640/console-query.png" width="640" /></a></div><br /><br /></div><div>You can see the results of a query in the Dataset pane on the lower right.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><div><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-k9q_HGN725g/UmkRhUaddxI/AAAAAAAAAGk/pKhYFFeynGI/s1600/console-dataset.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="212" src="/images/blog/-k9q_HGN725g/UmkRhUaddxI/AAAAAAAAAGk/pKhYFFeynGI/s640/console-dataset.png" width="640" /></a></div><br /></div><h3>Entities</h3><div>The Entities tab provides a tree view of an entity, plus the ability to drill in to related entities.</div><div><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-LX6uHUQV6DA/UmkRnb9C-OI/AAAAAAAAAGs/Sou-qlBDuNA/s1600/console-entities.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="/images/blog/-LX6uHUQV6DA/UmkRnb9C-OI/AAAAAAAAAGs/Sou-qlBDuNA/s640/console-entities.png" width="640" /></a></div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><h3>Transactions</h3><div>The Transactions tab provides a graphical view of the history of your database at scales ranging from days down to seconds.</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><div><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-H2qQ5agqrXM/UmkRr0HPP1I/AAAAAAAAAG0/VAFT0lVFLqc/s1600/console-transactions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="220" src="/images/blog/-H2qQ5agqrXM/UmkRr0HPP1I/AAAAAAAAAG0/VAFT0lVFLqc/s640/console-transactions.png" width="640" /></a></div><br /><br /></div><div>When you zoom in, the specific datoms in a transaction are displayed in the dataset pane.</div><h3>Indexes</h3><div>The Indexes tab allows you to browse ranges within a Datomic index, displaying results in the dataset pane.</div><div><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-Jn4Qe6YafhA/UmkR0RiHGwI/AAAAAAAAAG8/6v13UogZVM0/s1600/console-indexes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="/images/blog/-Jn4Qe6YafhA/UmkR0RiHGwI/AAAAAAAAAG8/6v13UogZVM0/s640/console-indexes.png" width="640" /></a></div><br /></div><div class="separator" style="clear: both; text-align: center;"></div><h3>And More</h3><div>This post only scratches the surface, see the <a href="http://docs.datomic.com/console.html" target="_blank">full docs</a> for more details. &nbsp;You can save arbitrary datasets, giving them a name for reuse in subsequent queries. &nbsp;And, of course, you can use Datomic's time features to work with as-of, since, and historical views of your data.</div><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>The Transaction Report Queue</title>
      <link>https://blog.datomic.com/2013/10/the-transaction-report-queue.html</link>
      <pubDate>Wed, 11 Sep 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/10/the-transaction-report-queue.html</guid>
      	<description>
        <![CDATA[
	Summary: Functional databases such as Datomic eliminate the burden of deciding what information a downstream observer needs. &nbsp;Just give 'em everything, lazily.<br /><h3>The Transaction Report Queue</h3>In Datomic, you can monitor all transactions.&nbsp; Any peer process in the system can request a <a href="http://docs.datomic.com/javadoc/datomic/Connection.html#txReportQueue--">transaction report queue</a> of every transaction against a particular database.<br /><br /><a href="https://github.com/Datomic/datomic-java-examples/blob/08f0baf2ac1846a425e746504532632b7dc6c707/src/java/datomic/samples/TxReportWatcher.java">TxReportWatcher</a>&nbsp;is a simple example of this. &nbsp;It watches a particular attribute in the database, and prints the entity id and value whenever a change to that attribute appears. &nbsp;The essence of the code is only a few lines of Java:<br /><br /><pre class="src src-java" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: #7f007f;">final</span> <span style="color: forestgreen;">BlockingQueue</span> <span style="color: sienna;">queue</span> = conn.txReportQueue();<br /><br /><span style="color: #7f007f;">while</span> (<span style="color: darkcyan;">true</span>) {<br /> <span style="color: #7f007f;">final</span> <span style="color: forestgreen;">Map</span> <span style="color: sienna;">tx</span> = queue.take();<br /> <span style="color: forestgreen;">Collection</span> <span style="color: sienna;">results</span> = q(byAttribute, tx.get(TX_DATA), attrid);<br /> <span style="color: #7f007f;">for</span> (<span style="color: forestgreen;">Iterator</span> <span style="color: sienna;">it</span> = results.iterator(); it.hasNext(); ) {<br /> printList(it.next());<br /> }<br />}</pre><br />There are several things to note here:<br /><div><ul><li>The Datomic query function <span style="font-family: Courier New, Courier, monospace;">q</span> is used to query the transaction data, showing that the full power of the database query language is available while handling transaction events.</li><li>The <span style="font-family: Courier New, Courier, monospace;">TX_DATA</span> map key points to all the data added to the database by this particular transaction.</li><li>Everything is made of generic data structures accessible from any JVM language: queues, collections, maps, and lists. &nbsp;(There is no ResultSet API.)</li></ul><h3>Context Matters</h3></div><div>How much information does a transaction observer need in order to take useful action? &nbsp;An easy but naive answer is "just the <span style="font-family: Courier New, Courier, monospace;">TX_DATA</span>".</div><div><br /></div><div>But when you move past toy systems and blog examples, context matters. &nbsp;For example, when a user places an order in a system, you might want to take different actions based on&nbsp;</div><div><ul><li>that user's order history</li><li>the current inventory status</li><li>time limited promotions</li><li>that user's relation to other users</li></ul><div>It is impossible to anticipate in advance the context you might need. &nbsp;But if you don't provide enough information, you will have to go back and ask for more. &nbsp;There are many risks here. &nbsp;The biggest risk is that such asking will introduce tighter coupling via the need for <i>coordination</i>, e.g. going back and asking questions of a database, questions that <i>must</i> be coordinated with the time of the event. &nbsp;Unnecessary coordination is a cause of complexity (and an enemy of scalability).</div><div><br /></div><div>Is there another way? &nbsp;You bet! &nbsp;If you have a functional database, where points in time are immutable values, then you can make&nbsp;<i>the entire database </i>available. &nbsp;Datomic provides exactly this. In addition to the <span style="font-family: Courier New, Courier, monospace;">TX_DATA</span> key, the <span style="font-family: Courier New, Courier, monospace;">DB_AFTER</span> key points to the entire database as of the completion of the transaction. &nbsp;And the <span style="font-family: Courier New, Courier, monospace;">DB_BEFORE</span> key points to the entire database <i>immediately before</i>&nbsp;the transaction started. &nbsp;Because both the "before" and "after" copies of the database are immutable values, no coordination with other processes is required, ever.</div><h3>A Common Misconception</h3>Developers often raise an objection to this approach: &nbsp;"Oh, I see, this approach is limited to tiny databases that can fit in memory and be passed around." &nbsp;Not at all. &nbsp;Because they are immutable, Datomic databases can be <i>lazily realized, </i>pulling into memory only the parts that are needed.<br /><br />Moreover, Datomic's indexes provide <i>leverage </i>over your data. Queries do not have to realize the entire database, they can use just the data needed. &nbsp;Datomic indexes provide leverage for "row", "column", "document", and "graph" access styles, so a wide variety of workloads are efficient. &nbsp;Different peers will "cache over" their working sets automatically, without you having to plan in advance which machine needs which data.<br /><ol></ol><h3>Composition FTW</h3><div>Datomic's transaction report queue makes it possible for any peer to observe and respond to transactions, with complete access to all necessary context, and without any coordination with database writes. &nbsp;Transaction reports are a simple building block for scalable systems.</div></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic MusicBrainz sample database</title>
      <link>https://blog.datomic.com/2013/07/datomic-musicbrainz-sample-database.html</link>
      <pubDate>Sat, 1 Jun 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/07/datomic-musicbrainz-sample-database.html</guid>
      	<description>
        <![CDATA[
	<a href="http://musicbrainz.org/">MusicBrainz</a> is an open music encyclopedia that collects music metadata and makes it available to the public. We are pleased to release a <a href="https://github.com/Datomic/mbrainz-sample">sample project</a> that uses the MusicBrainz dataset to help people get familiar with using <a href="http://datomic.com/">Datomic</a>.<br />The MusicBrainz dataset makes a great example database for learning, evaluating, or testing Datomic for a couple of reasons:<br /><ul><li>It deals with a domain with which nearly everyone is familiar</li><li>It is of decent size: 60,438 labels; 664,226 artists; 1,035,592 album releases; and 13,233,625 recorded tracks</li><li>It comprises a good number of entities, attributes, and relationships</li><li>It is fun to play with, query, and explore</li></ul><h2>Schema</h2>The <a href="http://github.com/Datomic/mbrainz-sample/tree/master/schema.edn">mbrainz-sample schema</a> is an adaptation of a subset of the full <a href="http://musicbrainz.org/doc/MusicBrainz_Database/Schema">MusicBrainz schema</a>. We didn't include some entities, and we made some simplifying assumptions and combined some entities. In particular:<br /><ul><li>We omit any notion of <a href="http://musicbrainz.org/doc/Work">Work</a></li><li>We combine Track, Tracklist and <a href="http://musicbrainz.org/doc/Recording">Recording</a> into simply "track"</li><li>We renamed <a href="http://musicbrainz.org/doc/Release_Group">Release group</a> to "abstractRelease"</li></ul><h3>Abstract Release vs. Release vs. Medium</h3>(Adapted from the MusicBrainz <a href="http://musicbrainz.org/doc/MusicBrainz_Database/Schema">schema docs</a>)<br />An "abstractRelease" is an abstract "album" entity (e.g. "The Wall" by Pink Floyd). A "release" is something you can buy in your music store (e.g. the 1984 US vinyl release of "The Wall" by Columbia, as opposed to the 2000 US CD release by Capitol Records).<br />Therefore, when you query for releases e.g. by name, you may see duplicate releases. To find just the "work of art" level album entity, query for abstractRelease.<br />The media are the physical components comprising a release (disks, CDs, tapes, cartridges, piano rolls). One medium will have several tracks, and the total tracks across all media represent the track list of the release.<br /><h3>Relationship Diagram</h3><a href="http://github.com/Datomic/mbrainz-sample/raw/master/schema.pdf" imageanchor="1"> <img border="0" src="//github.com/Datomic/mbrainz-sample/raw/master/relationships.png" /> </a><br /><h3>Entities</h3>For information about the individual entities and their attributes, please see the <a href="http://github.com/Datomic/mbrainz-sample/wiki/Schema">schema</a> page in the wiki, or the <a href="http://github.com/Datomic/mbrainz-sample/blob/master/schema.edn">EDN schema</a> itself.<br /><h2>Getting Started</h2>First <a href="https://github.com/Datomic/mbrainz-sample#getting-datomic">get Datomic</a>, and start up a transactor. <br /><h3>Getting the Data</h3>Next download the <a href="http://s3.amazonaws.com/mbrainz/datomic-mbrainz-backup-20130611.tar">mbrainz backup</a>:<br /><pre><code><br /> # 2.8 GB, md5 4e7d254c77600e68e9dc71b1a2785c53<br /> wget http://s3.amazonaws.com/mbrainz/datomic-mbrainz-backup-20130611.tar</code></pre>and extract:<br /><pre><code> # this takes a while<br /> tar -xvf datomic-mbrainz-backup-20130611.tar</code></pre>Finally, <a href="http://docs.datomic.com/backup.html">restore the backup</a>:<br /><pre><code> # takes a while, but prints progress -- ~150,000 segments in restore<br /> bin/datomic restore-db file:datomic-mbrainz-backup-20130611 datomic:free://localhost:4334/mbrainz</code></pre><h3>Getting the Code</h3>Clone the <a href="https://github.com/Datomic/mbrainz-sample">git repo</a> somewhere convenient:<br /><pre><code> git clone git@github.com:Datomic/mbrainz-sample.git<br /> cd mbrainz-sample</code></pre><h3>Running the examples</h3><h4>From Java</h4>Fire up your favorite IDE, and configure it to use both the included <a href="/Datomic/mbrainz-sample/blob/master/./pom.xml">pom.xml</a> and the following Java options when running: <pre><code><br /> -Xmx2g -server<br /></code></pre><h4>From Clojure</h4>Start up a Clojure REPL:<br /><pre><code> # from the root of the mbrainz-sample repo<br /> lein repl</code></pre>Then <a href="https://github.com/Datomic/mbrainz-sample/wiki/Queries"> connect to the database and run the queries</a>.<br /><h2>Thanks</h2>We would like to thank the MusicBrainz project for defining and compiling a great dataset, and for making it freely available.

  ]]>
	</description>
    </item>
    <item>
      <title>Component Entities</title>
      <link>https://blog.datomic.com/2013/06/component-entities.html</link>
      <pubDate>Sun, 19 May 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/06/component-entities.html</guid>
      	<description>
        <![CDATA[
	This post demonstrates <a href="http://www.datomic.com/" target="_blank">Datomic</a>'s component entities, and highlights a new way to create components available in today's release. &nbsp;You can follow along in the <a href="https://github.com/Datomic/datomic-groovy-examples/blob/master/src/main/Components.groovy" target="_blank">code</a>&nbsp;via the <a href="https://github.com/Datomic/datomic-groovy-examples" target="_blank">sample project</a>.<br /><br />The code examples use Groovy, a JVM language that combines similarity to Java with concision. &nbsp;If you are a Java developer new to Groovy, you may want to read <a href="http://blog.datomic.com/2013/06/using-datomic-from-groovy-part-1.html" target="_blank">this</a> first.<br /><h3>Why Components?</h3><div>In a database, some entities are their own identities, and others exist only as part of a larger parent entity. &nbsp;In Datomic, the latter entities are called&nbsp;<i>components, </i>and<i>&nbsp;</i>are reached from the parent via an attribute whose <a href="http://docs.datomic.com/schema.html" target="_blank">schema</a> includes&nbsp;<span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">:db/isComponent true</span>.&nbsp;</div><div><br /></div><div>As a familiar example, consider orders, line items, and products. &nbsp;Orders have references to line items, and those references are through a component attribute, since line items have no independent existence outside of an order. &nbsp;Line items, in turn, have references to products. &nbsp;References to products are <i>not </i>component references, because products exist regardless of whether or not they are part of any particular order.</div><div><br /></div><div>The schema for a line item component reference looks like this:</div><div><br /></div><div><pre class="src src-clojure" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">{<span style="color: darkslateblue;">:db/id</span> #db/id[<span style="color: darkslateblue;">:db.part/db</span>]<br /> <span style="color: darkslateblue;">:db/ident</span> <span style="color: darkslateblue;">:order/lineItems</span><br /> <span style="color: darkslateblue;">:db/isComponent</span> true<br /> <span style="color: darkslateblue;">:db/valueType</span> <span style="color: darkslateblue;">:db.type/ref</span><br /> <span style="color: darkslateblue;">:db/cardinality</span> <span style="color: darkslateblue;">:db.cardinality/many</span><br /> <span style="color: darkslateblue;">:db.install/_attribute</span> <span style="color: darkslateblue;">:db.part/db</span>}</pre></div><div><br /></div><div>Notice also that line items are <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">:db.cardinality/many</span>, since a single order can have many of them.</div><div><br /></div><div>Component attributes gain three special abilities in Datomic:</div><div><ul><li>you can create components via nested maps in a transaction (new in <a href="http://downloads.datomic.com/free.html">0.8.4020</a>)</li><li>touching an entity recursively touches all its components</li><li><span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">:db.fn/retractEntity</span> recursively deletes all its components</li></ul><div>Each of these abilities is demonstrated below.</div></div><h3>Creating Components</h3><div>To demonstrate line item components, let's create an order for some chocolate and whisky. &nbsp;First, here is a query for products <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?e</span> matching a particular description <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?v</span>:</div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">productQuery = <span style="color: #8b2252;">'''[:find ?e</span><br /><span style="color: #8b2252;"> :in $ ?v</span><br /><span style="color: #8b2252;"> :where [?e :product/description ?v]]'''</span>;</pre></div><div><br /></div><div>Now, we can query for the products we want to order:</div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">(chocolate, whisky) = [<span style="color: #8b2252;">'Expensive Chocolate'</span>, <span style="color: #8b2252;">'Cheap Whisky'</span>].collect {<br /> q(productQuery, conn.db(), it)[0][0];<br />}<br />===&gt; [17592186045454, 17592186045455]</pre></div><div><br /></div><div>The statement above uses Groovy's <a href="http://groovy.codehaus.org/Multiple+Assignment" target="_blank">multiple assignment</a>&nbsp;to assign chocolate to the first query result, and whisky to the second.</div><div><br /></div><div>Now that we have some products, we can create an order with some line items. As of today's release, you can do this via nested maps:</div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">order = [[<span style="color: #8b2252;">'order/lineItems'</span>: [[<span style="color: #8b2252;">'lineItem/product'</span>: chocolate,<br /> <span style="color: #8b2252;">'lineItem/quantity'</span>: 1,<br /> <span style="color: #8b2252;">'lineItem/price'</span>: 48.00],<br /> [<span style="color: #8b2252;">'lineItem/product'</span>: whisky,<br /> <span style="color: #8b2252;">'lineItem/quantity'</span>: 2,<br /> <span style="color: #8b2252;">'lineItem/price'</span>: 38.00]],<br /> <span style="color: #8b2252;">'db/id'</span>: tempid()]];</pre></div><div><br /></div><div>The nested maps above expand into two subentities. &nbsp;Notice that you do not need to create a <a href="http://docs.datomic.com/javadoc/datomic/Peer.html#tempid(java.lang.Object)" target="_blank">tempid</a> for the nested line items -- they will be auto-assigned tempids in the same partition as the parent order.</div><div><br /></div><div>The order above is pure data (a list of maps). This greatly facilitates development, testing, and composition. &nbsp;When we are ready to put the data in the database, the transaction is as simple as:</div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">conn.transact(order).get();</pre></div><h3>Touching Components</h3>Now we can query to find the order we just created. &nbsp;To demonstrate that query can reach anywhere within your data, we will do a multiway join to find the order via product description:<br /><br /><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">ordersByProductQuery = <span style="color: #8b2252;">'''</span><br /><span style="color: #8b2252;">[:find ?e</span><br /><span style="color: #8b2252;"> :in $ ?productDesc</span><br /><span style="color: #8b2252;"> :where [?e :order/lineItems ?item]</span><br /><span style="color: #8b2252;"> [?item :lineItem/product ?prod]</span><br /><span style="color: #8b2252;"> [?prod :product/description ?productDesc]]'''</span>;</pre><br />The query above joins<br /><br /><ul><li>from the provided <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">productDesc</span> input to to the product entity <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?prod</span></li><li>from <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?prod</span> to the order item <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?item</span></li><li>from <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?item</span> to the order <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?e</span></li></ul><div>and returns <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?e</span>.</div><div><br /></div><div>We are going to immediately pass <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">?e</span> to datomic's entity API, so let's take a moment to create a Groovy <a href="http://groovy.codehaus.org/Closures" target="_blank">closure</a> qe that automates query&nbsp;+ get entity:</div><div><br /></div><br /><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">qe = { query, db, <span style="color: forestgreen;">Object</span>[] <span style="color: sienna;">more</span> -&gt;<br /> db.entity(q(query, db, *more)[0][0])<br />}</pre><div></div><br /><div><br /></div><div>Now we can find an order the includes chocolate:</div><div><br /></div><br /><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">order = qe(ordersByProductQuery, db, <span style="color: #8b2252;">'Expensive Chocolate'</span>);</pre><div></div><br /><div><br /></div><div>Because the Datomic database is an immutable value in your own address space, entities can be lazily realized. &nbsp;When you first look at the order, you won't see any attributes at all:</div><div><br /></div><br /><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">===&gt; {:db/id 17592186045457}</pre><div></div><br /><div><br /></div><div>The <a href="https://docs.datomic.com/on-prem/clojure/index.html#datomic.api/touch" target="_blank">touch</a> API will realize all the immediate attributes of the order, plus it will recursively realize any components:</div><div><br /></div><br /><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">order.touch();<br />===&gt; {:order/lineItems #{{:lineItem/product #, <br /> :lineItem/price 38.00M, <br /> :lineItem/quantity 2, <br /> :db/id 17592186045459} <br /> {:lineItem/product #, <br /> :lineItem/price 48.00M, <br /> :lineItem/quantity 1, <br /> :db/id 17592186045458}}, <br /> :db/id 17592186045457}</pre><div></div><br /><div><br /></div><div>Notice that the line items are immediately realized, and you can see all their attributes. &nbsp;However, the products are <i>not</i> immediately realized, since they are not components. &nbsp; You can, of course, touch them yourself if you want.</div><h3>Retracting Components</h3><div>I am not as hungry or thirsty as I thought. &nbsp;Let's retract that order, using Datomic's <span style="font-family: &quot;courier new&quot; , &quot;courier&quot; , monospace;">:db.fn/retractEntity</span>:</div><div><br /></div><br /><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">conn.transact([[<span style="color: #8b2252;">":db.fn/retractEntity"</span>, order[<span style="color: #8b2252;">":db/id"</span>]]]).get();</pre><div></div><br /><div><br /></div><div>Retracting an entity will retract all its subcomponents, in this case the line items. &nbsp;To see that the line items are gone, we can count all the line items in our database:</div><div><br /></div><br /><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">q(<span style="color: #8b2252;">'''[:find (count ?e)</span><br /><span style="color: #8b2252;"> :where [?e :order/lineItems]]'''</span>,<br /> db);<br />===&gt; []</pre><div></div><br /><div><br /></div><div>References to non-components will not be retracted. &nbsp;The products are all still there:</div><div><br /></div><br /><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 15.0150146484375px; overflow: auto; padding: 5pt;">q(<span style="color: #8b2252;">'''[:find (count ?e)</span><br /><span style="color: #8b2252;"> :where [?e :product/description]]'''</span>,<br /> db);<br />===&gt; [[2]]</pre><div></div><br /><h3>Conclusion</h3><br />Components allow you to create substantial trees of data with nested maps, and then treat the entire tree as a single unit for lifecycle management (particularly retraction). &nbsp;All nested items remain visible as first-class targets for query, so<i> the shape of your data at transaction time does not dictate the shape of your queries</i>. &nbsp;This is a key value proposition of Datomic when compared to row, column, or document stores.

  ]]>
	</description>
    </item>
    <item>
      <title>Using Datomic from Groovy, Part 1: Everything is Data</title>
      <link>https://blog.datomic.com/2013/06/using-datomic-from-groovy-part-1.html</link>
      <pubDate>Sun, 12 May 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/06/using-datomic-from-groovy-part-1.html</guid>
      	<description>
        <![CDATA[
	In this post, I will demonstrate transacting and querying against <a href="http://www.datomic.com/" target="_blank">Datomic</a> from Groovy. &nbsp;The examples shown here are based on the following schema, for a simple social news application:<br /><br /><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-qUkSm8ZwVPs/UbeCD8Q4acI/AAAAAAAAAE0/I-cnU2l88j8/s1600/day-of-datomic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="202" src="/images/blog/-qUkSm8ZwVPs/UbeCD8Q4acI/AAAAAAAAAE0/I-cnU2l88j8/s320/day-of-datomic.png" width="320" /></a></div><br />There are a number of more in-depth <a href="https://github.com/Datomic/datomic-groovy-examples/tree/master/src/main" target="_blank">samples</a> in the <a href="https://github.com/Datomic/datomic-groovy-examples" target="_blank">datomic-groovy-examples</a> project on Github.<br /><h3>Why Groovy</h3><div><div>Groovy offers four key advantages for a Java programmer using Datomic:</div><div><ul><li>Groovy provides interactive development through <span style="font-family: Courier New, Courier, monospace;">groovysh</span>, the <a href="http://groovy.codehaus.org/Groovy+Shell" target="_blank">Groovy shell</a>. &nbsp;When combined with Datomic's dynamic, data-driven style, this makes it easy to interactively develop code in real time. &nbsp;The source code for this post has a number of other examples designed for interactive study within the Groovy shell.</li><li>Groovy's <a href="http://groovy.codehaus.org/Collections" target="_blank">collection literals</a> make it easy to see your data. &nbsp;Lists and maps are as easy as:</li></ul><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">aList = [<span style="color: #8b2252;">'John'</span>, <span style="color: #8b2252;">'Doe'</span>];<br />aMap = [firstName: <span style="color: #8b2252;">'John'</span>, <br /> lastName: <span style="color: #8b2252;">'Doe'</span>];</pre></div></div><div><ul><li>Groovy's <a href="http://groovy.codehaus.org/Closures" target="_blank">closures</a> make it easy to write functions, without the noise of single-method interfaces and anonymous inner classes. For instance, you could grab all the lastNames from a collection of maps</li></ul><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">lastNames = people.collect { it['<span style="color: #8b2252;">lastName'</span>] }</pre></div><br /><ul><li>Of the popular expressive languages that target the JVM, Groovy's syntax is most similar to Java's.</li></ul><h3>Transactions</h3><div><div>A Datomic <a href="http://docs.datomic.com/transactions.html" target="_blank">transaction</a> takes a list of data to be added to the database, and returns a <a href="http://docs.datomic.com/javadoc/datomic/ListenableFuture.html" target="_blank">future</a> map describing the results. The simplest possible transaction is a list of one sublist that adds an atomic fact, or <i>datom</i>, to the database, using the following shape:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">conn.transact([[<i>op, entityId, attributeName, value</i>]]);<br /></pre></div><div><br /></div><div><div>The components above are:</div><div><ul><li><span style="font-family: Courier New, Courier, monospace;">op</span> is a keyword naming the operation. <span style="font-family: Courier New, Courier, monospace;">:db/add</span> adds a datom, and <span style="font-family: Courier New, Courier, monospace;">:db/retract</span> retracts a datom.</li><li><span style="font-family: Courier New, Courier, monospace;">entityId</span> is the numeric id of an entity. &nbsp;You can use <span style="font-family: Courier New, Courier, monospace;"><a href="http://docs.datomic.com/javadoc/datomic/Peer.html#tempid(java.lang.Object)" target="_blank">tempid</a></span> when creating a new entity.</li><li><span style="font-family: Courier New, Courier, monospace;">attributeName</span> is a keyword naming an attribute.</li><li><span style="font-family: Courier New, Courier, monospace;">value</span> is the value of an attribute. &nbsp;The <a href="http://docs.datomic.com/schema.html" target="_blank">allowed types</a> for an attribute include numerics, strings, dates, URIs, UUIDs, binaries, and references to other entities.</li></ul></div></div><div><div>Keywords are names, prefixed with a colon, possibly with a leading namespace prefix separated by the slash char, e.g.</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">:hereIsAnUnqualifiedName<br />:the.namespace.comes.before/theName</pre></div><div><br /></div><div><div>Putting this all together, you might add a new user's first name with:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">conn.transact([[<span style="color: #8b2252;">':db/add'</span>, newUserId, <span style="color: #8b2252;">':user/firstName'</span>, <span style="color: #8b2252;">'John'</span>]]);<br /></pre></div><div><br /></div><div><div>If you are adding multiple datoms about the same entity, you can use a map instead of a list, with the special keyword <span style="font-family: Courier New, Courier, monospace;">:db/id</span> identifying the entity. &nbsp;For example, the following two transactions are equivalent:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;"><span style="color: firebrick;">// </span><span style="color: firebrick;">create an entity with two attributes (map form)</span><br />conn.transact([[<span style="color: #8b2252;">':db/id'</span>: newUserId,<br /> <span style="color: #8b2252;">':user/firstName'</span>: <span style="color: #8b2252;">'John'</span>,<br /> <span style="color: #8b2252;">':user/lastName'</span>: <span style="color: #8b2252;">'Doe'</span>]]);<br /><br /><span style="color: firebrick;">// </span><span style="color: firebrick;">create an entity with two attributes (list form)</span><br />conn.transact([[<span style="color: #8b2252;">':db/add'</span> newUserId, <span style="color: #8b2252;">':user/firstName'</span>, <span style="color: #8b2252;">'John'</span>],<br /> [<span style="color: #8b2252;">':db/add'</span> newUserId, <span style="color: #8b2252;">':user/lastName'</span>, <span style="color: #8b2252;">'Doe'</span>]]);<br /></pre></div><div><br /></div><div><div>Let's look next at composing larger transactions out of smaller building blocks. You have already seen creating a user:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">newUser = [[<span style="color: #8b2252;">':db/id'</span>: newUserId,<br /> <span style="color: #8b2252;">':user/email'</span>: <span style="color: #8b2252;">'john@example.com'</span>,<br /> <span style="color: #8b2252;">':user/firstName'</span>: <span style="color: #8b2252;">'John'</span>,<br /> <span style="color: #8b2252;">':user/lastName'</span>: <span style="color: #8b2252;">'Doe'</span>]];</pre></div><div><br /></div><div><div>Notice that this time we did not call transact yet, instead we just stored data describing the user into <span style="font-family: Courier New, Courier, monospace;">newUser</span>. &nbsp;&nbsp;</div><div><br /></div><div>Now imagine that you have a collection of story ids in hand, and you want to create a new user who upvotes those stories. &nbsp; Groovy's <span style="font-family: Courier New, Courier, monospace;"><a href="http://groovy.codehaus.org/groovy-jdk/java/util/Collection.html#collect(java.util.Collection, groovy.lang.Closure)" target="_blank">collect</a></span> method iterates over a collection, transforming values using a closure with a default single parameter named it. We can use collect to build new assertions that refer to each story in a collection of <span style="font-family: Courier New, Courier, monospace;">storyIds</span>:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">upvoteStories = storyIds.collect {<br /> [<span style="color: #8b2252;">':db/add'</span>, newUserId, <span style="color: #8b2252;">':user/upVotes'</span>, it]<br />}</pre></div><div><br />Now we are ready to build a bigger transaction out of the pieces. &nbsp;Because transactions are made of data, we don't need a special API for this. &nbsp;Groovy already has an API for concatenating lists, called <span style="font-family: Courier New, Courier, monospace;">+</span>:</div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">conn.transact(upvoteAllStories + newUser);</pre></div><div><br /></div><div><div>Building Datomic transactions from data has many advantages over imperative or object-oriented approaches:</div><div><ul><li>Composition is automatic, and requires no special API.</li><li>ACID transactionality is scoped to transaction calls, and does not require careful management across separate calls to the database.</li><li>Because they are data, Datomic transactions are flexible across system topology changes: they can be built offline for later use, serialized, and/or enqueued.</li></ul></div></div><h3>Query</h3><div><div>The Datomic <a href="http://docs.datomic.com/javadoc/datomic/Peer.html#q(java.lang.Object, java.lang.Object...)" target="_blank">query</a> API is named q, and it takes a query plus one or more inputs. The simple query below takes a query plus a single input, the database <span style="font-family: Courier New, Courier, monospace;">db</span>, and returns the id of every entity in the system with an email address:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">q(<span style="color: #8b2252;">'''[:find ?e </span><br /><span style="color: #8b2252;"> :where [?e :user/email]]'''</span>, db);</pre></div><div><br /></div><div><div>Keyword constants in the <span style="font-family: Courier New, Courier, monospace;">:where</span> clause constrain the results. &nbsp;Here, <span style="font-family: Courier New, Courier, monospace;">:user/email</span> constrains results to only those entities possessing an email. &nbsp;</div><div><br /></div><div>Symbols preceded by a question mark are <i>variables</i>, and will be populated by the query engine. &nbsp;The variable <span style="font-family: Courier New, Courier, monospace;">?e</span> will match every entity id associated with an email.</div><div><br /></div><div>A query always returns a set of lists, and the :<span style="font-family: Courier New, Courier, monospace;">find</span> clause specifies the shape of lists to return. &nbsp;In this example, the lists are of size one since a single variable <span style="font-family: Courier New, Courier, monospace;">?e</span> is specified by :<span style="font-family: Courier New, Courier, monospace;">find</span>.</div><div><br /></div><div>Note that the query argument to <span style="font-family: Courier New, Courier, monospace;">q</span> is notionally a list. &nbsp;As a convenience, you can pass the query argument as either a list or (as shown here) as an <a href="https://github.com/edn-format/edn" target="_blank">edn</a> string literal.</div></div><div><br /></div><div><div>The next query further constrains the result, to find a specific email address:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">q(<span style="color: #8b2252;">'''[:find ?e</span><br /><span style="color: #8b2252;"> :in $ ?email</span><br /><span style="color: #8b2252;"> :where [?e :user/email ?email]]'''</span>,<br /> db, <span style="color: #8b2252;">'editor@example.com'</span>);</pre></div><div><br /></div><div><div>There are several things to see here. &nbsp;There are now two inputs to the query: the database itself, and the specific email <span style="font-family: Courier New, Courier, monospace;">"editor@example.com"</span> we are looking for. &nbsp;Since there is more than one input, the inputs must be named by an <span style="font-family: Courier New, Courier, monospace;">:in</span> clause. &nbsp;The <span style="font-family: Courier New, Courier, monospace;">:in</span> clause names inputs in the order they appear:</div><div><ol><li><span style="font-family: Courier New, Courier, monospace;">$</span> is Datomic shorthand for a single database input.&nbsp;</li><li><span style="font-family: Courier New, Courier, monospace;">?email</span>&nbsp;is bound to the scalar <span style="font-family: Courier New, Courier, monospace;">"editor@example.com"</span>.</li></ol></div><div>Inputs need not be scalar. The shape<span style="font-family: Courier New, Courier, monospace;">&nbsp;[?varname ...] </span>in an <span style="font-family: Courier New, Courier, monospace;">:in</span> clause is called a <i>collection binding form</i>, and it binds a collection instead of a single value. The following query looks up two different users by email:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">q(<span style="color: #8b2252;">'''[:find ?e</span><br /><span style="color: #8b2252;"> :in $ [?email ...]</span><br /><span style="color: #8b2252;"> :where [?e :user/email ?email]]'''</span>,<br /> db, [<span style="color: #8b2252;">'editor@example.com'</span>, <span style="color: #8b2252;">'stuarthalloway@datomic.com'</span>]);</pre></div><div><br /></div><div><div>Another way to join is by having more than one constraint in a <span style="font-family: Courier New, Courier, monospace;">:where</span> clause. &nbsp;Whenever a variable appears more than once, it must match the same set of values in all the locations that it appears. &nbsp;The following query joins through <span style="font-family: Courier New, Courier, monospace;">?user</span> to find all the comments for a user:</div></div><div><br /></div><div><pre class="src src-groovy" style="background-color: #f3f5f7; border: 1pt solid rgb(174, 189, 204); font-family: courier, monospace; font-size: 14px; overflow: auto; padding: 5pt;">q(<span style="color: #8b2252;">'''[:find ?comment</span><br /><span style="color: #8b2252;"> :in $ ?email</span><br /><span style="color: #8b2252;"> :where [?user :user/email ?email]</span><br /><span style="color: #8b2252;"> [?comment :comment/author ?user]]'''</span>,<br /> db, <span style="color: #8b2252;">'editor@example.com'</span>)</pre></div><div><br /></div><div><div>We have only scratched the surface here. &nbsp;Datomic's <a href="http://docs.datomic.com/query.html" target="_blank">query</a> also supports rules, predicates, function calls, cross-database queries (with joins!), aggregates, and even queries against ordinary Java collections without a database. &nbsp;In fact, the <a href="http://en.wikipedia.org/wiki/Datalog" target="_blank">Datalog</a> query language used in Datomic supports a superset of the capabilities of the relational algebra that underpins SQL.</div><h3>Conclusion</h3><div>In this installment, you have seen the powerful, compositional nature of programming with generic data. &nbsp;In Part 2, we will look at the database as a value, and explore the implications of having a lazy, immutable database inside your application process.</div></div><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Sync</title>
      <link>https://blog.datomic.com/2013/06/sync.html</link>
      <pubDate>Fri, 3 May 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/06/sync.html</guid>
      	<description>
        <![CDATA[
	<br /><h4>Background</h4><a href="http://datomic.com/">Datomic</a>'s approach to updating peers uses a push model. Rather than have every read request route to the same server in order to get consistent data, data is stored immutably, and as soon as there is new information, all peers are notified. This completely eliminates polling any server. Thus, contrary to common presumption, when you ask the connection for the db value, there is no network communication involved: you are immediately given the local value of the db about which the connection was most recently informed.<br /><br />Everyone sees a valid, consistent view. You can never see partial transactions, corruption/regression of timelines, causal anomalies etc. Datomic is always 'business rules' valid, and causally consistent.<br /><h4>Motivation</h4>That does not mean that every peer sees the same thing simultaneously. Just as in the real world, it is never the case that everyone sees the same thing "at the same time" in a live distributed system. &nbsp;There is no inherent shared truth, as you might convey a message to me about X at the speed of light but I can only perceive X at the speed of sound. Thus, I know X is coming, but I might have to wait for it.<br /><br />This means that some peer A might commit a transaction and tell B about it before B is informed via the normal channels. This is an interesting case, as it has to do with perception and propagation delays. It is not a question of consistency, it is a question of communication synchronization.<br /><br />It comes up when you would like to read-your-own-writes via other peers (e.g. when a client hits different peer servers via a load balancer), and when there is out-of-band communication of writes (A tells B about its write before the transactor does).<br /><h4>Tools</h4>We've <a href="http://www.datomic.com/get-datomic.html">added</a> a new <b><i>sync</i></b> API to help you manage these situations.<br /><br />The <a href="https://docs.datomic.com/javadoc/datomic/Connection.html#sync(long)">first form of <b>sync</b></a> takes a basis point (T). It returns a future that will be fulfilled with a version of the db that includes point T. <i>This does not cause any additional interaction with the transactor </i>- the future will be filled by the normal communication on the update channels. But it saves you from having to poll for arrival. Most often, you will already have the requested T, and the future will complete immediately. This is the preferred method to use if you have any ability to convey the basis T, either in the message from A to B, or e.g. in cookies as a client hits different peers using a load balancer. You can easily <a href="https://docs.datomic.com/javadoc/datomic/Database.html#basisT()">get the basis T</a> for any db value you have in hand.<br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-nRloyHZAP20/UayuwohuYBI/AAAAAAAAAK8/z6SlbJ0kb2Q/s1600/oob42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="/images/blog/-nRloyHZAP20/UayuwohuYBI/AAAAAAAAAK8/z6SlbJ0kb2Q/s1600/oob42.png" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-ObD-XFzGRnA/UayvbDbcBAI/AAAAAAAAALQ/WIdFOhftQ48/s1600/lb42.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="/images/blog/-ObD-XFzGRnA/UayvbDbcBAI/AAAAAAAAALQ/WIdFOhftQ48/s1600/lb42.png" /></a></div>The <a href="https://docs.datomic.com/javadoc/datomic/Connection.html#sync()">second form of <b>sync</b></a> takes no arguments, and works via 'ping' of the transactor. It promises not to return until all transactions that have been acknowledged by the transactor at the time sync was called have arrived at this peer. Thus if A has successfully committed a transaction and told B about it, and B then calls <b>sync()</b>, the database returned by <b>sync</b> will include A's transaction.<br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-Lfg9_eHl1Vg/Uayv616aR8I/AAAAAAAAALY/IA62Z_BW7MA/s1600/sync.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="/images/blog/-Lfg9_eHl1Vg/Uayv616aR8I/AAAAAAAAALY/IA62Z_BW7MA/s1600/sync.png" /></a></div><div class="separator" style="clear: both; text-align: center;"></div><h4>Conclusion</h4>While these synchronization tools are powerful, make sure you use them only when necessary. The Datomic <a href="https://docs.datomic.com/javadoc/datomic/Connection.html#db()">defaults</a> were designed to leverage the inherent parallelism possible given immutable, accretion-only semantics and distributed storage. Notifications to peers are sent at the same time as the acknowledgement to the peer submitting the transaction, and thus are as 'simultaneous' as network communication can be. The sync tools need only be utilized to enforce cross-peer causal relationships.<br /><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>A Whirlwind Tour of Datomic Query</title>
      <link>https://blog.datomic.com/2013/05/a-whirlwind-tour-of-datomic-query_16.html</link>
      <pubDate>Tue, 16 Apr 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/05/a-whirlwind-tour-of-datomic-query_16.html</guid>
      	<description>
        <![CDATA[
	<h2 id="sec-1">Introduction</h2>This tour is to help those new to Datomic understand Datomic's built-in datalog by providing a simple domain and schema, and by walking through some use cases. &nbsp;For a more complete treatment of Datomic's query capabilities, please take a look at the <a href="http://docs.datomic.com/query.html" target="_blank">documentation</a>.<br /><h2 id="sec-1"><a href="https://www.blogger.com/blogger.g?blogID=4845864749156394488" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a>Reading the Code</h2><div class="separator" style="clear: both; text-align: center;"></div>To follow along in code, you can download Datomic Free Edition at <a href="http://downloads.datomic.com/free.html">http://downloads.datomic.com/free.html</a>, and the sample project at <a href="https://github.com/datomic/day-of-datomic">https://github.com/datomic/day-of-datomic</a>. The code examples should be executed interactively, in the order presented in the article, from a Clojure REPL. The complete code is in the <a href="https://github.com/Datomic/day-of-datomic/blob/9ff6f53bd2562bc49fc3f7c1b216103eb9705cce/tutorial/query_tour.clj">query_tour.clj file</a>. The <i><span style="font-family: Courier New, Courier, monospace;">=&gt;</span></i> prefix indicates responses that is printed by the REPL. The use of ellipsis (<i>…</i>) in output indicates that a larger result has been truncated for brevity.<br /><h2 id="sec-2">A Simple Schema</h2>The example queries that follow work against a simplified schema that you might use for a social news database, containing users, stories, and comments: <br /><a href="/images/blog/-q45Fo2EBeEE/UZUF5FVHWNI/AAAAAAAAAA0/8BzCsuLos58/s1600/social-news-schema.png" imageanchor="1" ><img border="0" src="/images/blog/-q45Fo2EBeEE/UZUF5FVHWNI/AAAAAAAAAA0/8BzCsuLos58/s320/social-news-schema.png" /></a> <br /><h2 id="sec-3">Get Connected</h2>In order to get a database connection, you will need to <i>require</i> namespaces for the Datomic API and for the news application, then setup a sample database. <br /><h3 id="sec-3-1">Listing 1: Getting Connected</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>require<br /> '[datomic.api <span style="color: darkslateblue;">:as</span> d]<br /> '[datomic.samples.news <span style="color: darkslateblue;">:as</span> news]<span style="color: #8c8c8c;">)</span><br /><br /> <span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">def</span> <span style="color: blue;">uri</span> <span style="color: #8b2252;">"datomic:mem://news"</span><span style="color: #8c8c8c;">)</span><br /> <span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">def</span> <span style="color: blue;">conn</span> <span style="color: #8c8c8c;">(</span>news/setup-sample-db-1 uri<span style="color: #8c8c8c;">))</span><br /></pre><h2 id="sec-4">Get a Database Value</h2>The connection from the previous step is already populated with a schema and sample data, but before you query against it, you must get the current <b>value</b> of the database. Syntactically this is trival: <br /><h3 id="sec-4-1">Listing 2: Getting a Database Value</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">def</span> <span style="color: blue;">db</span> <span style="color: #8c8c8c;">(</span>d/db conn<span style="color: #8c8c8c;">))</span><br /></pre><br />While the syntax of this step is trivial, the semantic implications are deep. Datomic queries do not happen "over there" in some database process, they happen here, in your process's memory space. <br /><h2 id="sec-5">A first query</h2>Users in the system are identified by a <i>:user/email</i> attribute. Lets find all of them: <br /><h3 id="sec-5-1">Listing 3: Finding All Users</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> ?e<br /> <span style="color: darkslateblue;">:where</span> [?e <span style="color: darkslateblue;">:user/email</span>]]<br /> db<span style="color: #8c8c8c;">)</span><br /> &nbsp;</pre><pre class="src src-clojure">=&gt; #{[17592186045424] [17592186045425]}<br /></pre><br />The large integers are entity ids. Entity ids are auto-assigned, so you may not see the same values on your system. There are several things to note here:<br /><ul><li>As query is the most commonly used function in Datomic, it has the terse name <i>d/q</i>. </li><li>The first argument is a query expression. The <i>:where</i> clause indicates what you want to find, "those entities <i>?e</i> that have a <i>:user/email</i> attribute." The <i>:find</i> clause tells which variables to return. </li><li>The second argument is the database value we obtained in the previous step. </li></ul><h2 id="sec-6">A simple join</h2>Rather than finding all users, let's query for a particular user. This requires joining two query inputs: the database value, and the email you are seeking: <br /><h3 id="sec-6-1">Listing 4: Finding a Specific User</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> ?e<br /> <span style="color: darkslateblue;">:in</span> $ ?email<br /> <span style="color: darkslateblue;">:where</span> [?e <span style="color: darkslateblue;">:user/email</span> ?email]]<br /> db<br /> <span style="color: #8b2252;">"editor@example.com"</span><span style="color: #8c8c8c;">)</span><br /> &nbsp;</pre><pre class="src src-clojure">=&gt; #{[17592186045425]}</pre><br />Notice that there are now three arguments to the query: the query expression plus the two inputs. Also, since there are two inputs, there is now an <i>:in</i> clause to name the inputs, in the order they appear, e.g. <i>$</i> binds the database, and <i>?email</i> binds "editor@example.com". Names starting with <i>$</i> name databases, and names starting with <i>?</i> name variables. <br /><h2 id="sec-7">A database join</h2>The previous join of a database to a single prebound variable may not even look like a join to you – in many databases this operation would be called a parameterized query. So let's look at a more traditional join, that leverages indexes in the database to associate more than one "type" of entity. The following query will find all of the editor's comments:<br /><h3 id="sec-7-1">Listing 5: Finding a User's Comments</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> ?comment<br /> <span style="color: darkslateblue;">:in</span> $ ?email<br /> <span style="color: darkslateblue;">:where</span> [?user <span style="color: darkslateblue;">:user/email</span> ?email]<br /> [?comment <span style="color: darkslateblue;">:comment/author</span> ?user]]<br /> db<br /> <span style="color: #8b2252;">"editor@example.com"</span><span style="color: #8c8c8c;">)</span><br /></pre><pre class="src src-clojure">=&gt; #{[17592186045451]<br /> [17592186045450]<br /> ... }<br /></pre><pre class="src src-clojure"></pre>Notice that the <i>:where</i> clause now has two data patterns: one associating users to their emails, and another associating comments to the user that authored them. Because the variable <i>?user</i> appears in both clauses, the joins on <i>?user</i>, finding only comments made by the editor.<br /><h2 id="sec-8">Aggregates</h2>You can obtain aggregates by changing the <i>:find</i> clause to include an aggregating function. Instead of finding the editor's comments, let's just <i>count</i> them: <br /><h3 id="sec-8-1">Listing 6: Returning an Aggregate</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> <span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">count</span> ?comment<span style="color: #8c8c8c;">)</span><br /> <span style="color: darkslateblue;">:in</span> $ ?email<br /> <span style="color: darkslateblue;">:where</span> [?user <span style="color: darkslateblue;">:user/email</span> ?email]<br /> [?comment <span style="color: darkslateblue;">:comment/author</span> ?user]]<br /> db<br /> <span style="color: #8b2252;">"editor@example.com"</span><span style="color: #8c8c8c;">)</span><br /> &nbsp;</pre><pre class="src src-clojure">=&gt; [[10]]<br /></pre><h2 id="sec-9">More joins</h2>Queries can make many joins. The following query joins comments to their referents, and joins the referents to <i>:user/email</i> to find any comments that are about people: <br /><h3 id="sec-9-1">Listing 7: Multiple Joins</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> <span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">count</span> ?comment<span style="color: #8c8c8c;">)</span><br /> <span style="color: darkslateblue;">:where </span>[?comment <span style="color: darkslateblue;">:comment/author</span>]<br /> [?commentable <span style="color: darkslateblue;">:comments</span> ?comment]<br /> [?commentable <span style="color: darkslateblue;">:user/email</span>]]<br /> db<span style="color: #8c8c8c;">)</span><br /></pre><pre class="src src-clojure">=&gt; []<br /></pre><br />No results is good news, because you don't want to let things get personal by allowing people to comment on other people. <br /><h2 id="sec-10">Schema-aware joins</h2>You cannot comment on people, but what kinds of things <b>can</b> you comment on? <br /><br />The three slots you have seen in data patterns so far are <i>entity</i>, <i>attribute</i>, and <i>value</i>. Up this point, the <i>entity</i> and <i>value</i> positions have typically been variables, but the <i>attribute</i> has always been constant. <br />That need not be the case. Here is a query that finds all the attributes of entities that have been commented on:<br /><h3 id="sec-10-1">Listing 8: A Schema Query</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> ?attr-name<br /> <span style="color: darkslateblue;">:where </span>[?ref <span style="color: darkslateblue;">:comments</span>]<br /> [?ref ?attr]<br /> [?attr <span style="color: darkslateblue;">:db/ident</span> ?attr-name]]<br /> db<span style="color: #8c8c8c;">)</span><br /></pre><pre class="src src-clojure">=&gt; #{[<span style="color: darkslateblue;">:story/title</span>]<br /> [<span style="color: darkslateblue;">:comment/body</span>]<br /> [<span style="color: darkslateblue;">:story/url</span>]<br /> [<span style="color: darkslateblue;">:comment/author</span>]<br /> [<span style="color: darkslateblue;">:comments</span>]}<br /></pre><br />Schema entities are ordinary entities, like any other data in the system. Rather then return their entity ids (<i>?attr</i> in the query above), you can join through <i>:db/ident</i> to find the programmatic identifiers that name each attribute. Judging from these attribute names, there are comments about stories and comments about other comments, exactly what you would expect given the schema.<br /><h2 id="sec-11">Entities</h2>In client/server databases where query happens in another process, it is often critical to get the answer and all of its details in a single query. (If you spread the work across multiple steps, you run the risk of the data changing between steps, leading to inconsistent results.) <br /><br />Since Datomic performs queries in-process, against an immutable database value, it is feasible to decompose the work of query into steps. One very decomposition is to use a query to <b>find</b> entities, and then to use Datomic's entity API to navigate to the relevant details about those entities. <br />Let's try it with the editor. First, use a query to find the editor's entity id: <br /><h3 id="sec-11-1">Listing 9: Finding an Entity ID</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">def</span> <span style="color: blue;">editor-id</span> <span style="color: #8c8c8c;">(</span>-&gt;&gt; <span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> ?e<br /> <span style="color: darkslateblue;">:in</span> $ ?email<br /> <span style="color: darkslateblue;">:where</span> [?e <span style="color: darkslateblue;">:user/email</span> ?email]]<br /> db<br /> <span style="color: #8b2252;">"editor@example.com"</span><span style="color: #8c8c8c;">)</span><br /> ffirst<span style="color: #8c8c8c;">))</span><br /></pre><pre class="src src-clojure"><span style="color: #8c8c8c;"><br /></span></pre>Notice that the query returns only the <i>?e</i>, not any particular attribute values. <br />Now, you can call <i>d/entity</i>, passing the database value and the entity id to get the editor entity. <br /><h3 id="sec-11-2">Listing 10: Getting an Entity</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">def</span> <span style="color: blue;">editor</span> <span style="color: #8c8c8c;">(</span>d/entity db editor-id<span style="color: #8c8c8c;">))</span><br /></pre><br />When you first look at an entity, it appears to be a mostly empty map: <br /><h3 id="sec-11-3">Listing 11: A Lazy Entity</h3><pre class="src src-clojure">editor<br /></pre><pre class="src src-clojure">=&gt; {<span style="color: darkslateblue;">:db/id</span> 17592186045425}<br /></pre><br />That is because entities are <b>lazy</b>. Their attribute values will appear once you ask for them: <br /><h3 id="sec-11-4">Listing 12: Requesting an Attribute</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">:user/firstName</span> editor<span style="color: #8c8c8c;">)</span><br /></pre><pre class="src src-clojure">=&gt; <span style="color: #8b2252;">"Edward"</span><br /></pre><br />If you are feeling more eager, you can <i>touch</i> an entity to immediately realize all of its attributes: <br /><h3 id="sec-11-5">Listing 13: Touching an Entity</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/touch editor<span style="color: #8c8c8c;">)</span><br /> =&gt; {<span style="color: darkslateblue;">:user/firstName</span> <span style="color: #8b2252;">"Edward"</span>,<br /> <span style="color: darkslateblue;">:user/lastName</span> <span style="color: #8b2252;">"Itor"</span>,<br /> <span style="color: darkslateblue;">:user/email</span> <span style="color: #8b2252;">"editor@example.com"</span>,<br /> <span style="color: darkslateblue;">:db/id</span> 17592186045425}<br /></pre><h2 id="sec-12">Are Entities ORM?</h2>No. Entities are used for some of the same purposes that you might use an ORM, but their capabilities are quite different. Entities differ from ORM objects in that the conversion between raw datoms and entities is entirely a mechanical process. There is never any configuration, and relationships are always available and (lazily!) navigable.<br /><br />Entities also differ from most ORM objects in that relationships can be navigated in either direction. In the previous code example, you saw how the <i>d/touch</i> method would automatically navigate all outbound relationships from an entity. However, you can also navigate <b>inbound</b> relationships, by following the convention of prefixing attribute names with an underscore. For example, a user's comments happen to be modeled as a relationship from the comment to the editor. To reach these comments from the editor entity, you can navigate the <i>:comment/author</i> attribute backwards:<br /><h3 id="sec-12-1">Listing 14: Navigating Backwards</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">-&gt;</span> editor <span style="color: darkslateblue;">:comment/_author</span><span style="color: #8c8c8c;">)</span><br /></pre><pre class="src src-clojure">=&gt; [{<span style="color: darkslateblue;">:db/id</span> 17592186045441}<br /> {<span style="color: darkslateblue;">:db/id</span> 17592186045443}<br /> ... ]<br /></pre><br />This process can, of course, be extended as far as you like, e.g. the following example navigates to all the comments people have made on the editor's comments: <br /><h3 id="sec-12-2">Listing 15: Navigating Deeper</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>-&gt;&gt; editor <span style="color: darkslateblue;">:comment/_author</span> <span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">mapcat</span> <span style="color: darkslateblue;">:comments</span><span style="color: #8c8c8c;">))</span><br /></pre><pre class="src src-clojure">=&gt; <span style="color: #8c8c8c;">(</span>{<span style="color: darkslateblue;">:db/id</span> 17592186045448}<br /> {<span style="color: darkslateblue;">:db/id</span> 17592186045450}<br /> ...<span style="color: #8c8c8c;">)</span><br /></pre><h2 id="sec-13">Time travel</h2>Update-in-place databases can tell you about the present, but most businesses need also to know about the past. Datomic provides this, by allowing you to take a value of a database as of a certain point in time. <br /><br />Given any datom, there are three time-related pieces of data you can request: <br /><ul><li>the transaction entity <i>tx</i> that created the datom </li><li>the relative time, <i>t</i> of the transaction </li><li>the clock time <i>:db/txInstant</i> of the transaction </li></ul>The transaction entity is available as a fourth optional component of any data pattern. The following query finds the transaction that set the current value for the editor's first name: <br /><h3 id="sec-13-1">Listing 16: Querying for a Transaction</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">def</span> <span style="color: blue;">txid</span> <span style="color: #8c8c8c;">(</span>-&gt;&gt; <span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> ?tx<br /> <span style="color: darkslateblue;">:in</span> $ ?e<br /> <span style="color: darkslateblue;">:where</span> [?e <span style="color: darkslateblue;">:user/firstName</span> _ ?tx]]<br /> db<br /> editor-id<span style="color: #8c8c8c;">)</span><br /> ffirst<span style="color: #8c8c8c;">))</span><br /></pre><br />Given a transaction id, the <i>d/tx-&gt;t</i> function returns the system-relative time that the transaction happened. <br /><h3 id="sec-13-2">Listing 17: Converting Transaction to T</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/tx-&gt;t txid<span style="color: #8c8c8c;">)</span><br />=&gt; 1023<br /><br /></pre>Relative time is useful for "happened-before" type questions, but sometimes you want to know the actual wall clock time. This is stored once per transaction, as the <i>:db/txInstant</i> property of the <b>transaction</b> entity: <br /><h3 id="sec-13-3">Listing 18: Getting a Tx Instant</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">-&gt;</span> <span style="color: #8c8c8c;">(</span>d/entity <span style="color: #8c8c8c;">(</span>d/db conn<span style="color: #8c8c8c;">)</span> txid<span style="color: #8c8c8c;">)</span> <span style="color: darkslateblue;">:db/txInstant</span><span style="color: #8c8c8c;">)</span><br /></pre><pre class="src src-clojure">=&gt; #inst <span style="color: #8b2252;">"2013-02-20T16:27:11.788-00:00"</span><br /></pre><br />Given a <i>t</i>, <i>tx</i>, or <i>txInstant</i> value, you can travel to that point in time with <i>d/as-of</i>. The example below goes back in time to before the point that the first name Edward was introduced, to see its past value: <br /><h3 id="sec-13-4">Listing 19: Going Back in Time</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">def</span> <span style="color: blue;">older-db</span> <span style="color: #8c8c8c;">(</span>d/as-of db <span style="color: #8c8c8c;">(</span>dec txid<span style="color: #8c8c8c;">)))</span><br /> &nbsp;</pre><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">:user/firstName</span> <span style="color: #8c8c8c;">(</span>d/entity older-db editor-id<span style="color: #8c8c8c;">))</span><br /></pre><pre class="src src-clojure">=&gt; <span style="color: #8b2252;">"Ed"</span><br /></pre><br />The example above shows an <i>as-of</i> value of the database being used as an argument to <i>d/entity</i>, but <i>as-of</i> values can be used anyhere a current database value can be used, including as an argument to query. <br /><h2 id="sec-14">Auditing</h2>While <i>as-of</i> is useful for looking at a moment in the past, you may also want to perform time-spanning queries. This is particularly true in audit scenarios, where you might want a complete history report of some value. <br /><br />To perform such queries, you can use the <i>d/history</i> view of a database, which spans all of time. The following query shows the entire history of the editor's <i>:user/firstName</i> attribute: <br /><h3 id="sec-14-1">Listing 20: Querying Across All Time</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span><span style="color: #7f007f;">def</span> <span style="color: blue;">hist</span> <span style="color: #8c8c8c;">(</span>d/history db<span style="color: #8c8c8c;">))</span><br /><br /><span style="color: #8c8c8c;">(</span>-&gt;&gt; <span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> ?tx ?v ?op<br /> <span style="color: darkslateblue;">:in</span> $ ?e ?attr<br /> <span style="color: darkslateblue;">:where</span> [?e ?attr ?v ?tx ?op]]<br /> hist<br /> editor-id<br /> <span style="color: darkslateblue;">:user/firstName</span><span style="color: #8c8c8c;">)</span><br /> <span style="color: #8c8c8c;">(</span><span style="color: darkslateblue;">sort-by</span> first<span style="color: #8c8c8c;">))</span><br /> &nbsp;</pre><pre class="src src-clojure">=&gt; <span style="color: #8c8c8c;">(</span>[13194139534319 <span style="color: #8b2252;">"Ed"</span> true]<br /> [13194139534335 <span style="color: #8b2252;">"Ed"</span> false]<br /> [13194139534335 <span style="color: #8b2252;">"Edward"</span> true]<span style="color: #8c8c8c;">)</span><br /></pre><br />The optional fifth field in a <i>:where</i> data pattern, named <i>?op</i> in the example above, matches true if a datom is asserted, or false if it is being retracted. <br /><br />Transaction 13194139534319 set the editor's first name to "Ed", and transaction 13194139534335 set it to "Edward". The cardinality of <i>:user/firstName</i> is one, which means that the system will only permit one value of that attribute per entity at any given time. To enforce this constaint, Datomic will automatically retract past values where necessary. Thus the transaction that asserts "Edward" also includes a retraction for the previous value "Ed". <br /><h2 id="sec-15">Everything is Data</h2>One of Datomic's design goals is "put declarative power in the hands of developers." Having queries that run in your process goes a long way to meet this objective, but what if you have data that is not in a Datomic database? <br /><br />Datomic's query engine can run without a database, against arbitrary data structures in your application. <br />The following example shows the query you began with, this time running against a plain Java list in memory: <br /><h3 id="sec-15-1">Listing 21: Querying Plain Java Data</h3><pre class="src src-clojure"><span style="color: #8c8c8c;">(</span>d/q '[<span style="color: darkslateblue;">:find</span> ?e<br /> <span style="color: darkslateblue;">:where</span> [?e <span style="color: darkslateblue;">:user/email</span>]]<br /> [[1 <span style="color: darkslateblue;">:user/email</span> <span style="color: #8b2252;">"jdoe@example.com"</span>]<br /> [1 <span style="color: darkslateblue;">:user/firstName</span> <span style="color: #8b2252;">"John"</span>]<br /> [2 <span style="color: darkslateblue;">:user/email</span> <span style="color: #8b2252;">"jane@example.com"</span>]]<span style="color: #8c8c8c;">)</span><br /></pre><pre class="src src-clojure">=&gt; #{[1] [2]}<br /></pre><br />The idea behind POJOs (plain old Java objects) is exactly right, and Datomic encourages you to take it one step further, to plain old lists and maps. 

  ]]>
	</description>
    </item>
    <item>
      <title>Excision</title>
      <link>https://blog.datomic.com/2013/05/excision.html</link>
      <pubDate>Wed, 10 Apr 2013 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2013/05/excision.html</guid>
      	<description>
        <![CDATA[
	<h4>Motivation</h4>It is a key value proposition of <a href="http://datomic.com/" target="_blank">Datomic</a> that you can tell not only what you know, but how you came to know it. &nbsp;When you add a fact:<br /><br /><span style="font-family: Courier New, Courier, monospace;">conn.transact(list(":db/add", 42, ":firstName", "John"));</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span>Datomic does more than merely record that 42's first name is "John". &nbsp;Each datom is also associated with a transaction entity, which records the moment (<span style="font-family: Courier New, Courier, monospace;">:db/txInstant</span>) the datom was recorded. <br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-SYxu8mIXnzg/UY0c5w3uSqI/AAAAAAAAAEQ/Lwd_N_eUQjI/s1600/john.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="/images/blog/-SYxu8mIXnzg/UY0c5w3uSqI/AAAAAAAAAEQ/Lwd_N_eUQjI/s640/john.png" height="112" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"></div><br />Given these <i>reified transactions</i>, it is possible to track the history of information. &nbsp;Let's say John decides he prefers to go by "Jack":<br /><div><br /><span style="font-family: Courier New, Courier, monospace;">conn.transact(list(":db/add", 42, ":firstName", "Jack"));</span><br /><div><span style="font-family: Courier New, Courier, monospace;"><br /></span></div><div>When you assert a new value for a cardinality-one attribute such as <span style="font-family: Courier New, Courier, monospace;">:firstName</span>, Datomic will automatically retract any past value (cardinality-one means that you cannot have two first names simultaneously). &nbsp;So now the database looks like this:</div><div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-3o3HDodfIEU/UY0dDdfP8WI/AAAAAAAAAEY/YBfuUfGjzLM/s1600/jack.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="/images/blog/-3o3HDodfIEU/UY0dDdfP8WI/AAAAAAAAAEY/YBfuUfGjzLM/s640/jack.png" height="198" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div></div><div>Given this information model, it is easy to see that Datomic can support queries that tell you:</div><div><ul><li>what you know now</li><li>what you knew at some point in the past</li><li>how and when you came to know any particular datom</li></ul></div><div>So far so good, but there is a fly in the ointment. &nbsp;In certain situations you may be forced to <i>excise&nbsp;</i>data, pulling it out root and branch and forgetting that you <i>ever</i> knew it. &nbsp;This may happen if you store data that must comply with privacy or IP laws, or you may have a regulatory requirement to keep records for seven years and then "shred" them. &nbsp;For these scenarios, Datomic provides excision.</div><h4>Excision in Datomic</h4></div><div>You can request excision of data by transacting a new entity with the following attributes:<br /><ul><li><span style="font-family: Courier New, Courier, monospace;">:db/excise</span> is required, and refers to a <i>target</i> entity or attribute to be excised. Thus there are two scenarios - excise all or part of an entity, or excise some or all of the values of a particular attribute.</li><li><span style="font-family: Courier New, Courier, monospace;">:db.excise/attrs</span> is an optional, cardinality-many, reference attribute that limits an excision to a set of attributes, useful only when the target of excise is an entity. (If <span style="font-family: Courier New, Courier, monospace;">:db.excise/attrs</span> are not specified, then all matching attributes will be excised.)</li><li><span style="font-family: Courier New, Courier, monospace;">:db.excise/beforeT</span>&nbsp;is an optional, long-valued attribute that limits an excision to only datoms whose t is before the specified <span style="font-family: Courier New, Courier, monospace;">beforeT</span>, which may be a t or tx id. This can be used with entity or attribute targets.</li><li><span style="font-family: Courier New, Courier, monospace;">:db.excise/before</span>&nbsp;is an optional, instant-valued attribute that limits an excision to only datoms whose transaction time is before the specified <span style="font-family: Courier New, Courier, monospace;">before</span>. This can be used with entity or attribute targets.</li></ul><h4>Example: Excising Specific Entities</h4>To excise a specific entity, manufacture a new entity with a :db/excise attribute pointing to that entity's id. &nbsp;For example, if user 42 requests that his personal data be removed from the system, the transaction data would be:<br /><br /><span style="font-family: Courier New, Courier, monospace;">[{:db/id #db/id[db.part/user],</span><br /><span style="font-family: Courier New, Courier, monospace;">&nbsp; :db/excise 42}]</span><br /><br />Since <span style="font-family: Courier New, Courier, monospace;">:db.excise/attrs</span> is not specified in the transaction data above, <i>all</i> datoms about entity 42 will be excised.<br /><div><h4>Example: Excising a Window in Time</h4></div><div><div>To excise old values of a particular attribute, you can create an excision for the attribute you want to eliminate, and then limit the excision using either <span style="font-family: Courier New, Courier, monospace;">before</span> or <span style="font-family: Courier New, Courier, monospace;">beforeT</span>. &nbsp;Imagine tracking application events that have users, categories, and details. &nbsp;Your application produces a ton of events, but you don't care about the old ones. &nbsp;Here is a transaction that will excise all the pre-2012 events:</div><div><br /></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; [{:db/id #db/id[db.part/user],</span></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; &nbsp; :db/excise :event/user</span></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; &nbsp; :db.excise/before #inst "2012"}</span></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; &nbsp;{:db/id #db/id[db.part/user],</span></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; &nbsp; :db/excise :event/category</span></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; &nbsp; :db.excise/before #inst "2012"}</span></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; &nbsp;{:db/id #db/id[db.part/user],</span></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; &nbsp; :db/excise :event/description</span></div><div><span style="font-family: Courier New, Courier, monospace;">&nbsp; &nbsp; :db.excise/before #inst "2012"}]</span></div></div><h4>Remembering <i>That</i> You Forgot</h4><div>It is a key value proposition of Datomic that you can tell not only what you know, but how you came to know it. &nbsp;This seems to be at odds with excision: if you remember what you forgot, then you didn't really forget it!</div><div><br /></div><div>You cannot remember <i>what</i> you forgot, but you can remember <i>that</i> you forgot. &nbsp;Excise attributes are ordinary attributes in the database, and you can query them. &nbsp;The following query would tell you if datoms about entity 42 have ever been excised:</div><div><br /></div><div><div><span style="font-family: Courier New, Courier, monospace;">[:find ?e :where [?e :db/excise 42]]</span></div></div><div><br /></div><div>Once you find those entities, you can of course use the entity API to navigate to the specific attribute and before filters of the excisions.</div><div><br /></div><div>Excise attributes are protected from excision, so you cannot erase your tracks. &nbsp;(Other important datoms such as schema are also protected, see the <a href="http://docs.datomic.com/excision.html" target="_blank">documentation</a> for full details.)<br /><h4>Handle With Care</h4><h4><span style="font-weight: normal;">Excision is different from any other operation in Datomic. &nbsp;While excision requests are transactions, excision itself is <i>not</i> transactional. &nbsp;Excision will happen on the next indexing job.</span></h4></div><div><span style="font-weight: normal;">Excision is permanent and unrecoverable. &nbsp;</span>Take a backup before performing significant excisions, and use excision only when your domain requires that you deliberately forget certain data. &nbsp;</div></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Riak and Couchbase Support</title>
      <link>https://blog.datomic.com/2012/11/riak-and-couchbase-support.html</link>
      <pubDate>Tue, 2 Oct 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/11/riak-and-couchbase-support.html</guid>
      	<description>
        <![CDATA[
	<br />We are pleased to announce today preliminary support for two new storage services for <a href="http://datomic.com/">Datomic</a>: Riak and Couchbase.<br /><br /><a href="http://basho.com/products/riak-overview/">Riak</a> is an elasticly scalable, distributed, redundant and highly available key-value store in the Dynamo model. It is a great option for Datomic users who want to run such a system system on their own premises (vs e.g. DynamoDB on AWS). Because Riak supports only eventual consistency at this time, a Datomic system running on Riak also utilizes Apache ZooKeeper, a highly-available coordination service. Datomic uses ZooKeeper for transactor failover coordination, and for the handful of keys per database that need to be updated with <a href="http://en.wikipedia.org/wiki/Compare-and-swap">CAS</a>. The bulk of the data is kept in Riak, immutably, and leverages all of Riak's redundancy and availability characteristics..<br /><br /><a href="http://www.couchbase.com/couchbase-server/overview">Couchbase</a> is an elasticly scalable, distributed and redundant document store. Like Riak, it supports redundant storage. Unlike Riak, it does offer consistency and CAS, trading off for a more conventional availability model, with either manual or automatic failover.<br /><br />Both solutions are backed&nbsp;with commercial support offerings from&nbsp;the people who make them.<br /><br />With all three services (Riak, ZooKeeper, Couchbase), Datomic can run on an existing installation alongside other applications without conflict. Thus you can combine your use of Datomic with other uses of the storages, at which they excel. We consider this hybrid use to be highly appealing in practice, as different parts of your applications have different requirements.<br /><br />As always, you can backup and restore to/from these storages and any other, and switch your application from one storage to another with a change to a different URI.<br /><br />This makes the set of Datomic storages:<br /><br /><ul><li>In-process memory</li><li>Transactor-local dev/free mode</li><li>SQL</li><li>DynamoDB</li><li>Riak</li><li>Couchbase</li><li>Infinispan</li></ul><br /><br />We are very excited about these new options, which greatly expand your choices, especially for non-cloud deployments. Each storage represents different tradeoffs, but what is important is that the choices are yours to make, as you decide what best fits your business and technical requirements.<br /><br />We look forward to your feedback as we fine tune these integrations for production use.<br /><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>codeq</title>
      <link>https://blog.datomic.com/2012/10/codeq.html</link>
      <pubDate>Mon, 10 Sep 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/10/codeq.html</guid>
      	<description>
        <![CDATA[
	<br /><h2><span style="font-size: x-large;">codeq</span></h2><h3><span>Backstory</span></h3>Programmer Sally: "<i>So, what are you going to do today Bob?"</i><br /><br />Programmer Bob: "<i>I'm not happy with the file baz.clj residing in my/ns. So I'm going to go to line 96 and change 2 to 42. I've been thinking about deleting line 124. If I have time, I'm also going to insert some text I've been working on at line 64."</i><br /><br />Programmer Sally: <i>(what's wrong with Bob?)</i><br /><h3>Short Story</h3><b><a href="https://github.com/Datomic/codeq#codeq">codeq</a></b>&nbsp;( 'co-deck') is a little application that imports your Git repositories into a <a href="http://datomic.com/">Datomic</a> database, then performs language-aware analysis on them, extending the Git model down from the file to the code quantum (<b><i>codeq</i></b>) level, and up across repos. By doing so, <b>codeq</b> allows you to:<br /><br /><ul><li>Track change at the program unit level (e.g. function and method definitions)</li><li>Query your programs and libraries declaratively, with the same cognitive units and names you use while programming</li><li>Query across repos</li></ul><br />The resulting database is highly programmable, and can serve as infrastructure for editors, IDEs, code browsing, analysis and documentation tools.<br /><br /><b>codeq</b> is open source (EPL), and <a href="https://github.com/Datomic/codeq">on github</a>. It works with <a href="http://www.datomic.com/get-datomic.html">Datomic Free</a>.<br /><br /><h3>Long Story</h3>We love Git. We use it, and by now so do most of you. Used conservatively, Git provides a good basis for information management (it keeps everything!).<br /><br />But it is important to understand Git's limits. Without a live connection to the editors, merge tools etc that munge the files, Git is relegated to simply discovering what has changed in the filesystem, and wisely just stores new stuff, using content-based addressing to determine what is new.<br /><br />Any further information we get from such a recording of novelty has to be derived.&nbsp;Diffs derive mechanical change information, and tree and file diffs are at the core of Git's facilities.<br /><br />Language-aware analyses can derive change information co-aligned with program semantics.<br /><br /><h4>How it works</h4>Git looks in directories and finds files, names them by the SHAs of their contents, and encodes their relationship to the enclosing tree by filename. During the import phase, <b>codeq</b> pretty much transfers Git's model intact.<br /><br />During the analysis phase, <b>codeq</b> looks in files and finds code segments, names them by their SHAs, and encodes their relationship to the enclosing file by line+column location. It further associates them with programmatic names and semantics (e.g. definition, or usage), if possible. We call this semantic segment a <b><i>codeq</i></b>.<br /><br />Thus, one way to understand <b>codeq</b> is as an extension of the git model and tree down to a finer granularity, aligned to program semantics.<br /><br /><b>codeq Model</b><br /><b><br /></b><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-rVnhRVfSFQ0/UHTuU7cbX_I/AAAAAAAAAKE/wT9IftO5QHM/s1600/codeq-overview.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="/images/blog/-rVnhRVfSFQ0/UHTuU7cbX_I/AAAAAAAAAKE/wT9IftO5QHM/s1600/codeq-overview.png" /></a></div><br />In Git, every repo is an island. When trying to understand the interactions across your entire program, including the many libraries it uses, each with their own Git repo, it becomes useful to combine repo information in a single database. The beauty of content-based addressing and globally unique namespacing (as done by e.g. Java and Clojure) is that such merging is conflict-free. So, <b>codeq</b> supports the importation of multiple repos into the same database and keeps them sorted, superimposing a level above the Git model.<br /><br /><h4>In Detail</h4>Now we can consider a particular scenario - a programmer edits a file, changing one function definition and inserting another.<br /><br />From the Git perspective, the two files are different blobs, with different SHAs, in different trees under the same name. Anything else it tells you about what has changed is done via dynamic diffing, and is usually expressed in terms of lines and blocks of text.<br /><br />Since we know (some of) these files are programs, and they are stored immutably, it seems worthwhile to perform a one-time analysis in order to track change more finely. <b>codeq</b> will break down the top level of the file into the corresponding program-language units (e.g. for Clojure, mostly function-defining forms). It gives each a SHA (if the block of code has never been seen before). It will then look inside and try to determine what the code is about (in context - since the same code can appear e.g. in different namespaces and thus name different things). The 'meaning' is normally some reference to a namespaced program identity, and for some purpose (definition, use). So a <i><b>codeq</b></i> encodes the location of a code segment in a file, and its semantics.<br /><br /><b>File edit:</b><br /><b><br /></b><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-ISvFQKIEr68/UHTu8e8TzgI/AAAAAAAAAKM/vaiDTVelo1I/s1600/codeq-file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="/images/blog/-ISvFQKIEr68/UHTu8e8TzgI/AAAAAAAAAKM/vaiDTVelo1I/s1600/codeq-file.png" /></a></div><br />After the edit, the analysis finds the identical first 2 segments in the same place in the new file, a new segment following, and then the old 3rd segment in a new location. The file ends with a new code segment, but is 'about' the same thing as the prior 4th segment. As time goes by we can get timelines for program constructs that are independent of the timelines of the files that contain them, and more closely aligned with our work (what's the history of this function definition?)<br /><br />This importation and analysis is not a one-shot thing. You continue to use Git normally. You can go back later and import your newer changes from Git, or perform new or enhanced analyses. &nbsp;Due to the first-class nature of Datomic transactions, the <b>codeq</b>&nbsp;database knows what has happened to it, what has been imported, what analyses have been run, what schemas have been installed etc.<br /><h3>Put on a happy interface</h3>Git has a powerful engine - durable persistent data structures with structural sharing and some fast C code that manipulates them. Unfortunately, it is hidden behind a plethora of command line utilities each of which has a boatload of options and a variety of outputs - let's have a parsing party!<br /><br />If only we had some declarative query technology with elegant support for recursion, we could turn all this tree walking into a piece of cake. Wait! - we can fight 1970's technology with... more 1970's technology - Datalog<br /><br /><pre><code><br />(def rules<br /> '[[(node-files ?n ?f) [?n :node/object ?f] [?f :git/type :blob]]<br /> [(node-files ?n ?f) [?n :node/object ?t] [?t :git/type :tree] <br /> [?t :tree/nodes ?n2] (node-files ?n2 ?f)]<br /> [(object-nodes ?o ?n) [?n :node/object ?o]]<br /> [(object-nodes ?o ?n) [?n2 :node/object ?o] [?t :tree/nodes ?n2] (object-nodes ?t ?n)]<br /> [(commit-files ?c ?f) [?c :commit/tree ?root] (node-files ?root ?f)]<br /> [(commit-codeqs ?c ?cq) (commit-files ?c ?f) [?cq :codeq/file ?f]]<br /> [(file-commits ?f ?c) (object-nodes ?f ?n) [?c :commit/tree ?n]]<br /> [(codeq-commits ?cq ?c) [?cq :codeq/file ?f] (file-commits ?f ?c)]])</code></pre><br /><br />You can follow along with <a href="https://github.com/downloads/Datomic/codeq/codeq.pdf">the schema</a>, but suffice to say, that is all the code you need to:<br /><br /><ul><li>Find all the files referenced by a commit</li><li>Find all the codeqs referenced by a commit</li><li>Find all the commits including a file</li><li>Find all the commits including a codeq</li></ul><br />This query uses those rules to find all of the different definitions of the function&nbsp;<span style="font-family: 'Courier New', Courier, monospace;">datomic.codeq.core/commit</span>, and when they were first defined:<br /><pre><code><br />(d/q '[:find ?src (min ?date)<br /> :in $ % ?name <br /> :where<br /> [?n :code/name ?name]<br /> [?cq :clj/def ?n]<br /> [?cq :codeq/code ?cs]<br /> [?cs :code/text ?src]<br /> [?cq :codeq/file ?f]<br /> (file-commits ?f ?c)<br /> (?c :commit/authoredAt ?date)]<br /> db rules "datomic.codeq.core/commit")<br /></code></pre><br /><br />If you don't know Datalog, it's worth the <a href="http://www.datomic.com/videos.html#query">11 minutes</a> it will take you to learn it.<br /><br /><hr /><br />I hope this gives you a sense of the motivation for <b><a href="https://github.com/Datomic/codeq#codeq">codeq</a></b>, and some excitement for trying it out. It's still early days, and we are definitely looking for help in enhancing the analysis, integrating with tools, supporting other languages etc.<br /><br />Have fun!<br /><br />Rich<br /><br /><br /><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Monitoring and Performance</title>
      <link>https://blog.datomic.com/2012/09/datomic-monitoring-and-performance.html</link>
      <pubDate>Fri, 17 Aug 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/09/datomic-monitoring-and-performance.html</guid>
      	<description>
        <![CDATA[
	I have just added a new section to the Datomic documentation on <a href="http://docs.datomic.com/monitoring.html" target="_blank">monitoring and performance</a>. If you are tuning Datomic, it is a must-read.<br /><br />I want to call attention in this blog post to one aspect of Datomic monitoring that might not be immediately apparent. Which is that you can use <a href="http://aws.amazon.com/cloudwatch/" target="_blank">Amazon CloudWatch</a> to monitor <i>any instance</i> of Datomic Pro, regardless of which storage you are using, and regardless of whether you are running any of your processes in the AWS cloud.<br /><br />Part of the value of a good cloud architecture is being able to mix-and-match the pieces.

  ]]>
	</description>
    </item>
    <item>
      <title>REST API</title>
      <link>https://blog.datomic.com/2012/09/rest-api.html</link>
      <pubDate>Mon, 6 Aug 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/09/rest-api.html</guid>
      	<description>
        <![CDATA[
	I'm pleased to announce that, starting with version 0.8.3488, <a href="http://datomic.com/">Datomic</a> now offers a REST API.<br /><br />There are a number of reasons to do this, first and foremost is that it will now be possible to access Datomic from non-JVM languages.<br /><br />How does it work?<br /><br />The command <b>bin/rest</b> will start up a peer which runs as a stand-alone HTTP server. You can access that service from any application using any language and any HTTP library. That's it!<br /><br /><br />This greatly enhances your architectural options:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-ugJZAKFpHQI/UElAWEFL-GI/AAAAAAAAAJA/6mFNSP96sJA/s1600/datomic-rest.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="/images/blog/-ugJZAKFpHQI/UElAWEFL-GI/AAAAAAAAAJA/6mFNSP96sJA/s1600/datomic-rest.png" /></a></div><br /><h3>Q&amp;A</h3><br /><b>So, does this make Datomic client-server?&nbsp;</b><br /><br />Yes and no. First off, the 'servers' are themselves peers, so you still get elastic, configuration-free horizontal query scalability by simply starting/stopping more peers. Second, the Datomic model, which substantially mitigates the problems of client-server databases, is faithfully replicated for clients:<br /><br /><ul><li>A peer service can serve more than one database, against more than one storage (Pro)</li><li>Clients get the same kind of data-driven API as do peers</li><li>Clients can get repeatable queries, and multiple queries with the same basis</li><li>Clients get the time-travel <i>as-of</i> and <i>since</i> capabilities, raw access to indexes and ranges</li><li>Clients can issue multi-datasource queries, and pass data to query</li><li>Clients can get a push feed of transaction events, via a Server-Sent Events source</li></ul><div><br /></div><div>Basically, it's just more options. Build full peers in a JVM language or lightweight clients in any language, or any combination.</div><div><br /></div><div><b>Do these clients count towards my peer count?</b>&nbsp;</div><div><br /></div><div>No. The clients do not run the Datomic peer library, and thus do not count. Each REST service process counts as a peer.</div><div><br /></div><div><b>Does this work with Datomic Free?</b>&nbsp;</div><div><br /></div><div>Yes it does.</div><div><br /></div><div><b>What's the status of the API?</b>&nbsp;</div><div><br /></div><div>It's still alpha, as we want to incorporate your feedback.</div><div><br /></div><div><div><b>Are there client libraries for language _______?</b></div><div><br /></div><div>Not yet. This is something we hope each language community will help us build.</div></div><div><br /></div><div><b>Where can I get more details?</b></div><div><br /></div><div>Check out the <a href="http://docs.datomic.com/rest.html">REST API docs</a></div><div></div><div><br /></div><div><br /></div><div>We hope you enjoy this new API and the capabilities it affords. As always, we welcome your feedback and input. If you've been on the sidelines waiting for Datomic to come to your favorite language - welcome!</div><div><br /></div>

  ]]>
	</description>
    </item>
    <item>
      <title>ElastiCache in 5 minutes</title>
      <link>https://blog.datomic.com/2012/09/elasticache-in-5-minutes.html</link>
      <pubDate>Fri, 3 Aug 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/09/elasticache-in-5-minutes.html</guid>
      	<description>
        <![CDATA[
	You can add ElastiCache to your AWS-based Datomic system in minutes:<br /><ul><li>Login to your <a href="https://console.aws.amazon.com/elasticache/home" target="_blank">ElastiCache management console</a>&nbsp;and choose "Launch Cache Cluster"</li><li>Complete the wizard. You can accept all defaults.</li><li>Back at the console, select "Cache Security Groups":<br /><a href="/images/blog/-W36wD_rUPbg/UDaKQ4sNZzI/AAAAAAAAACI/J9QET6OV9d8/s1600/SecurityGroups.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="161" src="/images/blog/-W36wD_rUPbg/UDaKQ4sNZzI/AAAAAAAAACI/J9QET6OV9d8/s200/SecurityGroups.png" width="200" /></a></li><li>... and authorize your Datomic system's security group (default is "datomic"):<br /><br /><a href="/images/blog/-26DKFEszYaA/UDaKgXBdcUI/AAAAAAAAACQ/Bp_vLj7Wxeg/s1600/Authorized.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="148" src="/images/blog/-26DKFEszYaA/UDaKgXBdcUI/AAAAAAAAACQ/Bp_vLj7Wxeg/s320/Authorized.png" width="320" /></a></li><li>Back at the console, select "Cache Clusters" and copy the node endpoints string:<br /><br /><a href="/images/blog/-KZfDK8mzh1Q/UDaKqKOfatI/AAAAAAAAACY/kMLtvgBWm_I/s1600/NodeEndpoints.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="92" src="/images/blog/-KZfDK8mzh1Q/UDaKqKOfatI/AAAAAAAAACY/kMLtvgBWm_I/s320/NodeEndpoints.png" width="320" /></a></li><li>Paste the node endpoints into your <a href="http://docs.datomic.com/storage.html" target="_blank">transactor properties</a> file:</li></ul><div><span style="font-family: 'Courier New', Courier, monospace; text-align: center;">&nbsp; &nbsp; memcached=</span><span style="font-family: Courier New, Courier, monospace;">foo.use1.cache.amazonaws.com:11211</span></div><div><ul><li><span style="font-family: Times, 'Times New Roman', serif;">Set the node endpoints in your peer application code:</span></li></ul><div style="font-family: Times, 'Times New Roman', serif;"><span style="font-family: 'Courier New', Courier, monospace; text-align: center;">&nbsp; &nbsp; System.setProperty</span></div><div style="font-family: Times, 'Times New Roman', serif;"><span style="font-family: 'Courier New', Courier, monospace; text-align: center;">&nbsp; &nbsp; ("datomic.memcachedServers",<br />&nbsp; &nbsp; &nbsp;"</span><span style="font-family: 'Courier New', Courier, monospace;">foo.use1.cache.amazonaws.com:11211);</span></div><div style="font-family: Times, 'Times New Roman', serif;"><span style="font-family: 'Courier New', Courier, monospace;"><br /></span></div><div><span style="font-family: inherit;">That's all there is to it. &nbsp;Datomic will <a href="http://blog.datomic.com/2012/07/memcache.html" target="_blank">transparently</a> use ElastiCache. There is no need to configure any cache timeouts, or change any code. Datomic's key names will not conflict with any other use, so you can use the cache for other tasks as well.</span></div></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;">You can also configure different caches for different process in the system. For example, I keep a local memcached process running at the office, so from a cold peer (my development laptop) queries are fast, even when I am connecting to a transactor that is running in the AWS cloud.</span></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Keep Chocolate Love Atomic</title>
      <link>https://blog.datomic.com/2012/08/atomic-chocolate.html</link>
      <pubDate>Tue, 10 Jul 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/08/atomic-chocolate.html</guid>
      	<description>
        <![CDATA[
	Datomic is a database of atomic facts, or datoms, that consist of&nbsp;entity, attribute, value, and transaction. For example, "I love&nbsp;chocolate (as of tx 1000)."<br /><br />Of couse, I am capable of loving many things, so the <span style="font-family: Courier New, Courier, monospace;"><b>:loves</b></span>&nbsp;attribute should be&nbsp;<span style="font-family: Courier New, Courier, monospace;"><b>:cardinality/many</b></span>. Here is an abbreviated&nbsp;history of my loves:<br /><br /><span style="font-family: Courier New, Courier, monospace;"><b>; some point in time...</b></span><br /><span style="font-family: Courier New, Courier, monospace;"><b>[[:db/add stu :loves :chocolate]</b></span><br /><span style="font-family: Courier New, Courier, monospace;"><b>&nbsp;[:db/add stu :loves :vanilla]]</b></span><br /><span style="font-family: Courier New, Courier, monospace;"><b><br /></b></span><span style="font-family: Courier New, Courier, monospace;"><b>; later...</b></span><br /><span style="font-family: Courier New, Courier, monospace;"><b>[[:db/add stu :loves :octomore]</b></span><br /><span style="font-family: Courier New, Courier, monospace;"><b>&nbsp;[:db/retract stu :loves :vanilla]]</b></span><br /><br />The set of all things I currently love is <i>derived</i> information, and it can be&nbsp;calculated from the history of atomic facts. Based on the transactions&nbsp;above, I currently love <span style="font-family: Courier New, Courier, monospace;"><b>:chocolate</b></span> and <span style="font-family: Courier New, Courier, monospace;"><b>:octomore</b></span>.<br /><br />Datomic automatically handles this derivation, as can be seen through&nbsp;the <a href="http://docs.datomic.com/javadoc/index.html" target="_blank">entity</a> interface:<br /><br /><span style="font-family: Courier New, Courier, monospace;"><b>stu.get(:loves)&nbsp;</b></span><br /><span style="font-family: Courier New, Courier, monospace;"><b>=&gt; #{:chocolate :octomore}</b></span><br /><br />Now, imagine creating a web interface with checkboxes for different&nbsp;things a person might love. &nbsp;You initially populate the interface with&nbsp;my current loves, pulled from the database. I interact with the&nbsp;system, and you get back a set of checkbox states.<br /><br />At this point, you should submit adds and retracts <i>only</i> for the new&nbsp;facts I created -- not a set with an add or retract for every UI&nbsp;element. This is a subtle point. If I liked chocolate before, and I&nbsp;didn't uncheck chocolate, what is the harm in saying "Stu likes&nbsp;chocolate" again?<br /><br />The biggest problem is that you are lying to the database. I <i>didn't</i>&nbsp;repeat my love of chocolate. What if the system also had a user&nbsp;interface more subtle than checkboxes, that allowed me to reiterate&nbsp;past preferences? You wouldn't be able to tell the difference.<br /><br />An obvious warning sign is when you find yourself submitting derived&nbsp;information (the set of my likes) when you actually have the facts&nbsp;(what I just said) in hand. Ignoring facts and recording derived&nbsp;information is always perilous -- imagine managing a system that&nbsp;records birthdays and ages, but not birthdates.<br /><br />A more subtle mistake is to abuse transactions to extract facts from derived&nbsp;information. You have a new derived set in hand, and the database&nbsp;knows how to calculate the previous derived set. Given those two&nbsp;things, you could write a <a href="http://docs.datomic.com/database-functions.html" target="_blank">transaction function</a> that takes the two sets&nbsp;and backtracks to figure out what changed.<br /><br />This approach has a variant of the dishonesty problem mentioned&nbsp;before, in that it provides no way for me to reiterate my love for&nbsp;chocolate. But the other problem with this approach may be even worse:&nbsp;It imposes coordination in the <i>implementation</i>, where no coordination&nbsp;was required by the <i>domain</i>.<br /><br />Let's say that I choose, at some point in time, to start liking&nbsp;<span style="font-family: Courier New, Courier, monospace;"><b>:cheesecake</b></span> and <span style="font-family: Courier New, Courier, monospace;"><b>:nachos</b></span>. These are atomic choices, requiring no&nbsp;coordination with any historical record. If you send Datomic a set of all checkbox states, and ask it to discover&nbsp;<span style="font-family: Courier New, Courier, monospace;"><b>:cheesecake</b></span>&nbsp;and&nbsp;<b style="font-family: 'Courier New', Courier, monospace;">:nachos </b>inside a transaction,&nbsp;you are manufacturing a coordination job that has no&nbsp;basis in reality. Unnecessary coordination is an enemy of scalability&nbsp;and reuse.<br /><br />The root cause of confusion here is update-in-place thinking. The&nbsp;checkbox model exposes derived<br />information (the current states) but not the facts (the choices the&nbsp;user made). Given the set of checkbox states, you should do the diff&nbsp;in the web tier as soon as you pull data out of the form. This still&nbsp;has the problem that there is no way to restate that you love&nbsp;chocolate, but now the scope of the problem is localized to its cause&nbsp;-- the checkbox model. You can fix the problem, or not (you often&nbsp;don't care, which is why checkboxes work the way they do). But at&nbsp;least you are not propagating the problem into the permanent record.<br /><br />Datomic is built on an <a href="http://www.datomic.com/rationale.html#DataModel" target="_blank">understanding</a> that data is created by atomic&nbsp;addition, not by corruptive modification. When your input source has&nbsp;an update-in-place model (such as checkbox states), you should convert&nbsp;to atomic facts before creating a transaction.<br /><br />Now go eat some <a href="http://www.domori.com/" target="_blank">chocolate</a>.<br /><br />

  ]]>
	</description>
    </item>
    <item>
      <title>Memcache Support</title>
      <link>https://blog.datomic.com/2012/07/memcache.html</link>
      <pubDate>Sun, 24 Jun 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/07/memcache.html</guid>
      	<description>
        <![CDATA[
	<span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">We're happy to announce today transparent integrated support for memcached in Datomic Pro Edition.</span><br /><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">One of the nice things about the Datomic architecture is that the index segments kept in storage are immutable. That enables them to be cached extensively. Currently that caching happens inside the peers, which keep segments they have needed thus far in the application process heap.</span><br /><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">While this is great for process-local working sets, there is only so much a single machine can cache. So, we've added support for an optional second tier of distributed, shared cache, leveraging a memcached cluster. This tier of cache can be as large as you wish, and is shared between all the peers.</span><br /><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><span style="">The entire use of memcached is automatic and integrated - just provide the endpoints of your memcached cluster in configuration.&nbsp;</span>The peer protocols will automatically both look in it, and populate it on cache misses. Being based upon immutability, there are no cache coherence problems nor expiration policy woes.</span><br /><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">The architecture incorporating memcached looks like this:</span><br /><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><div class="separator" style="clear: both; text-align: center;"><a href="/images/blog/-bQXEj6HWB2Q/V8caoGETT9I/AAAAAAAAAKY/WfXRpkyTPTouDTSaA8XzIgVhyvaRCnJ3ACLcB/s1600/DArch.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="627" src="/images/blog/-bQXEj6HWB2Q/V8caoGETT9I/AAAAAAAAAKY/WfXRpkyTPTouDTSaA8XzIgVhyvaRCnJ3ACLcB/s640/DArch.jpg" width="640" /></a></div><br /> <span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">The benefits of this are many:</span><br /><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><br /><ul><li><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">You can get a shared cache of arbitrary size - many deployments will be able to fit their entire database in memcached if desired.&nbsp;</span></li><li><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">If you are using a storage that is not otherwise distributed (e.g. unclustered PostgreSQL), the memcached tier can both almost entirely remove the read load on the single server and distribute it.</span></li><li><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Even when using a distributed storage like DynamoDB, the memcached tier can reduce your read provisioning and increase speed.</span></li><li><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Developers can set up a small memcached daemon locally so their DB will always feel 'hot' across process restarts.</span></li><li><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">The memcached tier will enable hybrid strategies where the peers, transactors and memcached are all local but the storage is remote (e.g. DynamoDB).</span></li></ul><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">Datomic is a good citizen in its use of memcached - it doesn't need to 'own' the cluster, and all of the Datomic keys incorporate UUIDs so they won't conflict with other application-level use of the same memcached cluster.</span><br /><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;"><br /></span><span class="Apple-style-span" style="font-family: &quot;arial&quot; , &quot;helvetica&quot; , sans-serif;">We hope you enjoy this feature, which is included in the Pro Edition at no extra charge.</span>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Editions and Pricing</title>
      <link>https://blog.datomic.com/2012/07/editions-and-pricing.html</link>
      <pubDate>Sun, 24 Jun 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/07/editions-and-pricing.html</guid>
      	<description>
        <![CDATA[
	<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Over the past few months we've gotten feedback and input regarding our pricing and licensing, and we've revamped them to make things simpler and clearer. The subscription pricing made people feel as if the offering was a service (it's not), as well as brought about misgivings about termination etc, so we've dropped it.&nbsp;</span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Here's the new offering:</span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br /><ul><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">We've added <a href="http://blog.datomic.com/2012/07/datomic-free-edition.html">Datomic Free Edition</a> - it's free and redistributable</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Datomic Pro is licensed software.</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">It is offered with a perpetual license.</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Maintenance (updates and support) for the first 12 months is included.</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Maintenance in subsequent years is ~50% of the license fee.</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Pricing is yearly, and up front on web site.</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Pricing is based upon the number of processes&nbsp;(transactors + peers)&nbsp;using the software in production in your organization.</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Development and testing usage doesn't count against your license limits</span></li></ul><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">We've priced it such that the expenditure for maintenance roughly correlates to our older subscription pricing.</span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Evaluation has changed a bit as well. In all modes, Datomic Pro will require a license key. You can get a free 30-day eval key via the web site. There is no longer a 'runs for a week without a key' mode.</span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Note that Datomic is not just for cloud deployments - our SQL and other storage support lets you run it on-premise or in the cloud.</span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">You can get more information on the <a href="http://datomic.com/get-datomic.html">editions and pricing</a> here.</span>

  ]]>
	</description>
    </item>
    <item>
      <title>Datomic Free Edition</title>
      <link>https://blog.datomic.com/2012/07/datomic-free-edition.html</link>
      <pubDate>Sun, 24 Jun 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/07/datomic-free-edition.html</guid>
      	<description>
        <![CDATA[
	<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">We're happy to announce today the release of Datomic Free Edition. This edition is oriented around making <a href="http://datomic.com/">Datomic</a> easier to get, and use, for open source and smaller production deployments.</span><br /><ul><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Datomic Free Edition is ... free!</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">The system supports transactor-local storage</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">The peer library includes a memory database and Datomic Datalog</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">The Free transactor and peers are freely redistributable&nbsp;</span></li><li><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">The transactor supports 2 simultaneous peers</span></li></ul><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Of particular note here is that Datomic Free Edition comes with a redistributable license, and does not require a personal/business-specific license from us. That means you can download Datomic Free, build e.g. an open source application with it, and ship/include Datomic Free binaries with your software. You can also put the Datomic Free bits&nbsp;into public repositories and package managers (as long as you retain the licenses and copyright notices).</span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">There is a ton of capability included in the Free Edition, including the Datomic in-process memory database (great for testing), and the Datomic datalog engine, which works on both Datomic databases and in-memory collections. That's right, free datalog for everyone.</span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">You can use Datomic Free Edition in production, and you can use it in commercial applications.</span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Datomic Free edition is completely API-compatible with what we are now calling Datomic Pro edition (the one that pays the bills). Datomic Pro adds the ability to use additional storages like SQL and DynamoDB, support for more peers, as well as high-availabilty mode for transactors and our new memcache support.</span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">You can read about the <a href="http://datomic.com/get-datomic.html">editions</a> here.&nbsp;</span></div><div><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div><div><a href="http://datomic.com/get-datomic.html"><span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;">Get Datomic!</span></a></div>

  ]]>
	</description>
    </item>
    <item>
      <title>Welcome</title>
      <link>https://blog.datomic.com/2012/07/welcome.html</link>
      <pubDate>Sun, 17 Jun 2012 00:00:00 +0200</pubDate>
      <guid isPermaLink="false">2012/07/welcome.html</guid>
      	<description>
        <![CDATA[
	Welcome to the Datomic blog!

  ]]>
	</description>
    </item>

  </channel> 
</rss>
