dynamodb-simple: Typesafe library for working with DynamoDB database

[ bsd3, database, library ] [ Propose Tags ]

Framework for accessing DynamoDB database. The majority of AWS API is available to the user in a convenient, simple and typesafe manner.

[Skip to Readme]


Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees


  • No Candidates
Versions [RSS],,,,,,,
Change log changelog.md
Dependencies aeson, amazonka, amazonka-core, amazonka-dynamodb (>=1.6.0), base (>=4.9 && <5), bytestring (>=, conduit, containers, double-conversion, exceptions, generics-sop, hashable, lens, monad-loops, mtl, scientific, semigroups, tagged, template-haskell, text, transformers, unordered-containers, uuid-types, vector [details]
License BSD-3-Clause
Copyright Ondrej Palkovsky
Author Ondrej Palkovsky
Maintainer palkovsky.ondrej@gmail.com
Category Database
Home page https://github.com/ondrap/dynamodb-simple
Bug tracker https://github.com/ondrap/dynamodb-simple/issues
Source repo head: git clone https://github.com/ondrap/dynamodb-simple.git
Uploaded by ondrap at 2019-05-17T19:50:30Z
Reverse Dependencies 1 direct, 0 indirect [details]
Downloads 5231 total (19 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs available [build log]
Last success reported on 2019-05-17 [all 1 reports]

Readme for dynamodb-simple-

[back to package description]

DynamoDB layer for Haskell

Build Status Hackage

This library intends to simplify working with DynamoDB AWS database. It uses Generics code (generics-sop) on top of your structures and just by adding a few instances allows you to easily generate AWS commands.

data Test = Test {
    category :: T.Text
  , user     :: T.Text
  , subject  :: T.Text
  , replies  :: Int
} deriving (Show)
-- Generate instances and category', user' etc. variables for queries/updates
mkTableDefs "migrate" (tableConfig "" (''Test, WithRange) [] [])

test :: IO ()
test = do
  lgr  <- newLogger Info stdout
  setEnv "AWS_SECRET_ACCESS_KEY" "XXXXXXXXXXXXXXfdjdsfjdsfjdskldfs+kl"
  env  <- newEnv Discover
  let dynamo = setEndpoint False "localhost" 8000 dynamoDB
  let newenv = env & configure dynamo & set envLogger lgr
  runResourceT $ runAWS newenv $ do
      migrate mempty Nothing -- Create tables, indices etc.
      putItem (Test "news" "john" "test" 20)
      item <- getItem Eventually tTest ("news", "john")
      liftIO $ print item
      items <- scanCond tTest (replies' >. 15) 10
      liftIO $ print items


  • Global secondary indexes.
  • Local secondary indexes.
  • Tables with only hash keys as well as tables with combined hash and sort key.
  • Sparse indexes (define the column as Maybe in a table, omit the Maybe in index definition).
  • Automatically generate polymorphic lenses to access fields in main table and index records.
  • Standard datatypes including Tagged and basic default instances for data types supporting Show/Read.
  • New types can be added easily.
  • High-level, easy-to-use API - hides intricacies of both DynamoDB and amazonka library.
  • Type-safe conditions, including nested structures.
  • Type-safe update actions.
  • Template-haskell macro to easily create all relevant instances.
  • 'Schema migration' - upon startup checks if the database schema matches the definition and, if possible, adjusts the database. If it is impossible, it fails.
  • Automatic handling of invalid values (empty strings, empty sets). Automatic rewriting of queries when searching for these empty values.
  • Compatible with GHC8 DuplicateRecordFields
  • Customizable table and index names. Custom translation of field names to attribute names.
  • AWS Dynamo streaming settings.
  • Utilities to help with simulated joins or retriving original data from index.
  • Both conduit and page-based API.

What is planned

  • Support for automatic versioning of fields.


  • Projections are not supported. Using some generic programming on tuples it should be possible.
  • You cannot compare attributes between themselves (i.e. currentAccount' >=. averageAccount'). I'm not sure this would be currently technically possible. Does anybody need it?

Handling of NULLs

DynamoDB does not accept empty strings/sets. It accepts NULL, but that is not acceptable in fields that are used for sparse indexing.

Empty string and empty set are represented by omitting the value.

  • Just Nothing :: Maybe (Maybe a) will become Nothing on retrieval.
  • [Just 1, Nothing, Just 3] will become [Just 1, Just 3] on retrieval.
  • HashMap Text (Maybe a) is not a good idea; missing values will disappear.
  • Maybe (Set a) will become Nothing on empty set
  • Don't try to use inequality comparisons (>., <.) on empty strings.
  • If you use maybeCol' == Nothing, it gets internally replaced by attr_missing(maybeCol), so it will behave as expected. The same with empty String or Set. Keep that in mind when traversing nested structures.
  • In case of schema change, Maybe columns are considered Nothing.
  • In case of schema change, String columns are decoded as empty strings, Set columns as empty sets, [a] columns as empty lists.
  • Condition for == "", == [] etc. is automatically enhanced to account for non-existent attributes (i.e. after schema change).
  • Empty list/empty hashmap is represented as empty list/hashmap; however it is allowed to be decoded even when the attribute is missing in order to allow better schema migrations.