Type-safe, multi-backend data serialization.

Version on this page:
LTS Haskell 22.30:
Stackage Nightly 2024-07-24:
Latest on Hackage:

See all snapshots persistent appears in


Type-safe, data serialization. You must use a specific backend in order to make this useful. For more information, see the chapter in the Yesod book.


Changelog for persistent

  • #1528
    • The PersistField Int{,8,16,32,64} instances will now work with a PersistRational, provided that the denominator is 1. This fixes the bug where SUM in Postgres would change the type of a column being summed.

  • #1477
    • Qualified references to other tables will work
  • #1503
    • Create Haddocks from entity documentation comments
  • 1497
    • Always generates SymbolToField "id" instance
  • #1509
    • Provide ViaPersistEntity for defining PathMultiPiece for entity keys.
  • #1480
    • Add mpsAvoidHsKeyword in MkPersistSettings

  • #1513
    • Support GHC 9.8 and aeson-2.2

  • #1496
    • Fixes name shadowing error at the generated keyFromRecordM function.
  • #1505
    • Fixes the comment line parsing rule so that accommodates paragraph breaks.

  • #1469
    • Change default implementation for insertUnique_ to not perform unecessary queries (mirrors 1449)
  • #1437
    • Add existsBy to PersistUniqueRead

  • #1460
    • Remove extraneous map toPersistValue call in the mkInsertValues function, as it evaluates to id.
  • #1476
    • Fix mkRecordName to suffix _ if the field name matches any of Haskell keywords.

  • #1460
    • Fix a problem where a Primary key causes mkPersist to generate code that doesn’t compile under NoFieldSelectors

  • #1452
    • Implement repsert as a special case of respertMany. Allows backend specific behavior.

  • #1451
    • Support mtl >= 2.3

  • #1449
    • Default implementation for insert_ which doesn’t perform any unnecessary queries.

  • #1440
    • Defined NFData PersistValue

  • #1446
    • Foreign key discovery was fixed for qualified names, Key Model, and Maybe references.
  • #1438
    • Clarify wording on the error message for null in unique constraint
  • #1447
    • Fix SafeToInsert not being generated correctly for some Id columns

  • #1428
    • Fix that the documentation for discoverEntities was not being generated.

  • #1425
    • Introduce an alias setPsUseSnakeCaseForeignKeys for setPsUseSnakeCaseForiegnKeys due to a typo in the latter; deprecate setPsUseSnakeCaseForiegnKeys

  • #1421
    • Add mpsCamelCaseCompositeKeySelector field to MkPersistSettings, which define the style of the entity’s composite key.

  • #1418
    • Re-export SafeToInsert from Database.Persist.Class, which should re-export it through Database.Persist, Database.Persist.Sql, etc.
  • #1409
    • Fix incorrect reference to rawSql in documentation.

  • #1411
    • Fix the docs for FieldNameDB, and update FieldDef.fieldComments docs since the quasiquoter supports field comments now.

  • #1407
    • Fix a name shadowing warning.

  • #1392
    • Enhance selectList documentation with TypeApplications examples.
    • Clarify selectSource documentation wording.
  • #1391
    • Increasing quasi module test coverage, improve error assertions
  • #1401
    • Change Entity back into a regular record and drop the HasField instance. This is technically a breaking change, but the bug in GHC’s COMPLETE annotations rendered a super common pattern a much more invasive breaking change than anticipated. As a result, upgrading to persistent-2.14 was untenable.

      If you did upgrade and this broke your codebase again, please let me know and I can release another patch to shim it.

  • #1343
    • Implement Type Literal based field definitions
  • #1387
    • Better UX with insert. We now report a type error when you try to insert an Entity or a function, and we also forbid inserting if the database would throw an error missing a primary key.
  • #1383
    • Primary keys have a NonEmpty of fields, not a [] of fields.
    • A Primary key on an entity now creates a Unique constructror for that record, with the name #{entityName}PrimaryKey. This also affects the generation of AtLeastOneUniqueKey and OnlyOneUniqueKey instances, so you may need to change behavior on these classes.
  • #1381
    • Entity is given a HasField instance that uses the database field names. This is primarily done to support OverloadedRecordDot in GHC 9.2 and above.
    • A consequence of this is that the Entity constructor has been renamed to Entity'. A pattern synonym is provided that should work in almost all cases. You may incur a MonadFail m constraint if you are pattern matching directly on the constructor in a do result.
  • #1364
    • The type SomePersistField was removed in favor of using PersistValue directly.
  • #1386
    • The module Database.Persist.Class.DeleteCascade was deleted since you can put cascade behavior directly on your database models.
    • Removed mkSave from Database.Persist.TH. Use mkEntityDefList instead.
    • Remove the CompositeDef constructor from ReferenceDef which was not used internally anymore.
  • #1385
    • The support for entity-level sum types is deprecated. It adds a considerable amount of complexity to the code, and the pattern is not particularly good for actually supporting sum types in most databases.
  • #1384
    • Add tabulateEntityA to the PersistEntity class, allowing you to construct an Entity a by providing a function EntityField a t -> f t. Note that this doesn’t make sense for sum entities, and the implementation errors.
    • Add tabulateEntity as a pure version of that.

  • #1374
    • Increasing test coverage for errors thrown when parsing entity definitions

  • #1379
    • mkPersist now generates code that compiles under NoFieldSelectors and DuplicateRecordFields even if field labels are not prefixed
  • #1376
    • Add coverage for parsing nested parens/lists in field types
  • #1370
    • Add spec to assert Persistent.TH is the only import required when defining entities

  • #1369
    • Fix withObject needing to be imported

  • #1315
    • Refactor entity constraint parsing in Quasi module

  • #1341
    • Add SqlBackendHooks to allow for instrumentation of queries.
  • #1327
    • Update SqlBackend to use new StatementCache interface instead of IORef (Map Text Statement)

  • #1351
    • aeson-2.0 support

  • #1329
    • Prevent discovery of constrained PersistEntity instances in discoverEntities (since the discovered instances won’t work without constraints anyway).

  • #1314

    • Fix typos and minor documentation issues in Database.Persist and Database.Persist.Quasi.
  • #1317

    • Expose orderClause from the Persistent internals, which allows users to produce well-formatted ORDER BY clauses.
  • #1319

    • Add a Num instance for OverflowNatural

  • #1308
    • Consolidate the documentation for the Persistent quasiquoter in Database.Persist.Quasi.
  • #1312
    • Reorganize documentation and link to more modules.
    • Expose Database.Persist.Sql.Migration

  • #1294
    • Fix an issue where documentation comments on fields are in reverse line order.

  • #1264
    • Support declaring Maybe before the type in model definitions

  • #1277
    • Corrected the documentation of addMigration to match the actual behaviour - this will not change the behaviour of your code.

  • #1287
    • Fix the duplicate entity check for transitive dependencies.
    • Fixes an issue where generating code would refer to the ModelName when making a reference to another table when the explicit code only refers to ModelNameId.

  • #1268
    • Show keyFromValues error

  • #1244
    • Implement config for customising the FK name
  • #1252
    • mkMigrate now defers to mkEntityDefList and migrateModels instead of fixing the foreign key references itself.
    • mkSave was deprecated - the function did not fix foreign key references. Please use mkEntityDefList instead.
    • EntityDef will now include fields marked MigrationOnly and SafeToRemove. Beforehand, those were filtered out, and mkMigrate applied. The function getEntityFields will only return fields defined on the Haskell type - for all columns, see getEntityFieldsDatabase.
  • #1225
    • The fields and constructor for SqlBackend are no longer exported by default. They are available from an internal module, Database.Persist.Sql.Types.Internal. Breaking changes from Internal modules are not reflected in the major version. This will allow us to release new functionality without breaking your code. It’s recommended to switch to using the smart constructor functions and setter functions that are now exported from Database.Persist.Sql instead.

    • A new API is available for constructing and using a SqlBackend, provided in Database.Persist.SqlBackend. Instead of using the SqlBackend directly, use mkSqlBackend and the datatype MkSqlBackendArgs. The MkSqlBackendArgs record has the same field names as the SqlBackend, so the translation is easy:

      - SqlBackend
      + mkSqlBackend MkSqlBackendArgs
          { connInsertSql = ...
          , connCommit = ...
          , connEscapeFieldName = ...
          , connEscapeTableName = ...
          , etc

      Some fields were omitted in MkSqlBackendArgs. These fields are optional - they provide enhanced or backend-specific functionality. For these, use the setter functions like setConnUpsertSql.

    • Previously hidden modules are now exposed under the Internal namespace.

    • The connLimitOffset function used to have a Bool parameter. This parameter is unused and has been removed.

  • #1234
    • You can now customize the default implied ID column. See the documentation in Database.Persist.ImplicitIdDef for more details.
    • Moved the various Name types into Database.Persist.Names
    • Removed the hasCompositeKey function. See hasCompositePrimaryKey and hasNaturalKey as replacements.
    • The EntityDef constructor and field labels are not exported by default. Get those from Database.Persist.EntityDef.Internal, but you should migrate to the getters/setters in Database.Persist.EntityDef as you can.
    • Added the Database.Persist.FieldDef and Database.Persist.FieldDef.Internal modules.
    • The PersistSettings type was made abstract. Please migrate to the getters/setters defined in that Database.Persist.Quasi, or use Database.Persist.Quasi.Internal if you don’t mind the possibility of breaking changes.
    • Add the runSqlCommand function for running arbitrary SQL during migrations.
    • Add migrateModels function for a TH-free migration facility.
  • #1253
    • Add discoverEntities to discover instances of the class and return their entity definitions.
  • #1250
    • The mpsGeneric function has been deprecated. If you need this functionality, please comment with your needs on the GitHub issue tracker. We may un-deprecate it, or we may provide a new and better means of facilitating a solution to your problem.
  • #1255
    • mkPersist now checks to see if an instance already exists for PersistEntity for the inputs.
  • #1256
    • The QuasiQuoter has been refactored and improved.
    • You can now use mkPersistWith to pass in a list of pre-existing EntityDef to improve foreign key detection and splitting up models across multiple modules.
    • The entityId field now returns an EntityIdDef, which specifies what the ID field actually is. This is a move to better support natural keys.
    • Several types that had lists have been refactored to use nonempty lists to better capture the semantics.
    • mkDeleteCascade is deprecated. Please use the Cascade behavior directly on fields.
    • You can use Key Foo and FooId interchangeably in fields.
    • Support for GHC < 8.4 dropped.

  • #1258
    • Support promoted types in Quasi Quoter
  • #1243
    • Assorted cleanup of TH module
  • #1242
    • Refactor setEmbedField to use do notation
  • #1237
    • Remove nonEmptyOrFail function from recent tests

  • #1231
    • Simplify Line type in Quasi module, always use NonEmpty
  • #1229
    • The #id labels are now generated for entities.

  • #1218
    • Refactoring name generating functions in TH
  • #1226
    • Expose the filterClause and filterClauseWithValues functions to support the upsertWhere functionality in persistent-postgresql.

  • #1123
    • Fix JSON encoding for PersistValue

  • Refactoring token parsing in quasi module #1206
  • Removing duplication from TH output #1202
  • Refactor [] to NonEmpty in Quasi module #1193
  • #1162
    • Replace askLogFunc with askLoggerIO
  • Decomposed HaskellName into ConstraintNameHS, EntityNameHS, FieldNameHS. Decomposed DBName into ConstraintNameDB, EntityNameDB, FieldNameDB respectively. #1174
  • Use resourcet-pool to break out some Data.Pool logic #1163
  • #1178
    • Added ‘withBaseBackend’, ‘withCompatible’ to ease use of base/compatible backend queries in external code.
  • Added GHC 8.2.2 and GHC 8.4.4 back into the CI and persistent builds on 8.2.2 again #1181
  • #1179
    • Added Compatible, a newtype for marking a backend as compatible with another. Use it with DerivingVia to derive simple instances based on backend compatibility.
    • Added makeCompatibleInstances and makeCompatibleKeyInstances, TemplateHaskell invocations for auto-generating standalone derivations using Compatible and DerivingVia.
  • #1207
    • @codygman discovered a bug in issue #1199 where postgres connections were being returned to the Pool SqlBackend in an inconsistent state. @parsonsmatt debugged the issue and determined that it had something to do with asynchronous exceptions. Declaring it to be “out of his pay grade,” he ripped the poolToAcquire function out and replaced it with Data.Pool.withResource, which doesn’t exhibit the bug. Fortunately, this doesn’t affect the public API, and can be a mere bug release.
    • Removed the functions unsafeAcquireSqlConnFromPool, acquireASqlConnFromPool, and acquireSqlConnFromPoolWithIsolation. For a replacement, see runSqlPoolNoTransaction and runSqlPoolWithHooks.
  • Renaming values in persistent-template #1203
  • #1214:
    • Absorbed the persistent-template package. persistent-template will receive a 2.12 release with a warning and a deprecation notice.
    • Remove the nooverlap flag. It wasn’t being used anymore.
  • #1205
    • Introduce the PersistLiteral_ constructor, replacing the PersistLiteral, PersistLiteralEscaped, and PersistDbSpecific.
    • The old constructors are now pattern synonyms. They don’t actually differentiate between the various escaping strategies when consuming them! If you pattern match on multiple of PersistDbSpecific, PersistLiteral, or PersistLiteralEscaped , then you should use the PersistLiteral_ constructor to differentiate between them.

  • Fix a bug where an empty entity definition would break parsing of EntityDefs. #1176

  • Docs/Bugs fixes #1153
    • Fix documentation on FieldDef.fieldAttrs.
    • Postgresql backend: Add a space in cascade clause of generated SQL.

  • Foreign Key improvements #1121

    • It is now supported to refer to a table with an auto generated Primary Kay
    • It is now supported to refer to non-primary fields, using the keyword References
    • It is now supported to have cascade options for simple/single-field Foreign Keys
  • Introduces a breaking change to the internal function mkColumns, which can now be passed a record of functions to override its default behavior. #996

  • Added explicit forall notation to make most API functions play nice when using TypeApplications. (e.g. instead of selectList @_ @_ @User [] [], you can now write selectList @User [] []) #1006

  • #1060

    • The QuasiQuoter now supports OnDelete and OnUpdate cascade options.
  • #1044

    • Field and constraint labels generated by TH can now be customized.
    • mpsPrefixFields is deprecated in favor of using these customisation functions.
  • #1032

    • Instance for Natural is removed. See OverflowNatural for a replacement and rationale on why.
  • #1063

    • A new class member keyFromRecordM allows you to construct a Key record from a record if it was defined with Primary.
  • #1036

    • The method entityIdFromJSON that is used to parse entities now correctly works for entities that define a custom Primary key.
  • #856

    • Modify upsertBy to use backend-specific implementation (if any).
  • #1066

    • You can set a column’s sql=id for a non Id column.
  • Fix a bug where unsafe migration error messages were being shown using Show prior to printing, resulting in less helpful output. #1080

  • #1087

    • RawSql now has tuple instances up to GHC’s max tuple size (62)
  • #1076

    • Loc is now imported from monad-logger as opposed to template-haskell. Removes template-haskell as an explicit dependency.
  • #1114

    • Remove unnecessary deriving of Typeable.
  • #1128

    • Remove Monad constraint on entityDef
  • #1127

    • Remove deriving of Show for uniques. Users that need a Show instance can put a standalone deriving instance:

      deriving stock instance Show (Unique User)
  • #1131

    • Add an exists function to the PersistQueryRead type class.
  • #1117

    • Allow parsing UTCTimes from sqlite with the format “%F %T%Q” as well, instead of only “%FT%T%Q”.
  • #1140

    • A new function checkUniqueUpdateable allows you to check uniqueness constraints on an entity update without having to update it.
  • #1142

    • Deprecate hasCompositeKey in favor of hasCustomPrimaryKey and hasCompositePrimaryKey functions.
  • #1098

    • Add support for configuring the number of stripes and idle timeout for connection pools
      • For functions that do not specify an idle timeout, the default has been bumped to 600 seconds.
        • This change is based off the experience of two production codebases. See #775
      • Add a new type ConnectionPoolConfig to configure the number of connections in a pool, their idle timeout, and stripe size.
      • Add defaultConnectionPoolConfig to create a ConnectionPoolConfig
      • Add createSqlPoolWithConfig and withSqlPoolWithConfig, which take this new data type
  • #1122, #1152

    • Adds a new constructor, PersistLiteral ByteString to PersistValue to support unescaped SQL literals.

      • Obviously, this is highly unsafe, and you should never use it with user input.
    • Adds a new field, cGenerated :: Maybe Text to Column for backend-specific support of generated columns.

      • Express generated fields in the Persistent DSL
          fieldOne Text Maybe
          fieldTwo Text Maybe
          fieldThree Text Maybe generated=COALESCE(field_one,field_two)
      • Support for MySQL >= 5.7. (No version checking is performed! Using this feature with older versions of MySQL will cause runtime SQL exceptions!)
      • Support for Postgresql >= 12. (No version checking is performed! Using this feature with older versions of Postgresql will cause runtime SQL exceptions!)
      • Support for SQLite >= 3.31 (same caveat applies; support added in #1152 )
  • #1151

    • Allow OverloadedLabels to be used with the EntityField type.

  • #1041
    • Explicit foreign keys can now reference tables with custom sql name
    • Add qualified names to the stock classes list.

  • #1024
    • Add the ability to do documentation comments in entity definition syntax. Unfortunately, TemplateHaskell cannot add documentation comments, so this can’t be used to add Haddocks to entities.
    • Add Haddock explainers for some of the supported entity syntax in Database.Persist.Quasi


  • Add the EntityWithPrefix type to allow users to specify a custom prefix for raw SQL queries. #1018
  • Added Acquire based API to Database.Persist.Sql for working with connections/pools in monads which aren’t MonadUnliftIO. #984


  • Log exceptions when closing a connection fails. See point 1 in yesod #1635. #978


  • Added support for GHC 8.8 about MonadFail changes #976


  • Added runMigrationQuiet and runMigrationUnsafeQuiet to Database.Persist.Sql.Migration as safer alternatives to runMigrationSilent. #971 This functions as workaround/fix for: #966, #948, #640, and #474
  • Added RawSql instances for 9, 10, 11 and 12-column results. #961


  • Added constraint= attribute to allow users to specify foreign reference constraint names.


  • Added two type classes OnlyOneUniqueKey and AtLeastOneUniqueKey. These classes are used as constraints on functions that expect a certain amount of unique keys. They are defined automatically as part of the persistent-template’s generation. #885
  • Add the entityComments field to the EntityDef datatype, and fieldComments fields to the FieldDef datatype. The QuasiQuoter does not currently know how to add documentation comments to these types, but it can be expanded later. #865
  • Expose the SqlReadT and SqlWriteT constructors. #887
  • Remove deprecated Connection type synonym. Please use SqlBackend instead. #894
  • Remove deprecated SqlPersist type synonym. Please use SqlPersistT instead. #894
  • Alter the type of connUpsertSql to take a list of unique definitions. This paves the way for more efficient upsert implementations. #895


  • Add documentation for the Migration type and some helpers. #860


  • Fix #847: SQL error with putMany on Sqlite when Entity has no unique index.


  • Added support for SQL isolation levels to via SqlBackend. [#812]
  • Move Database.Persist.Sql.Raw.QQ to a separate persistent-qq package #827
  • Fix 832: repsertMany now matches mapM_ (uncurry repsert) and is atomic for supported sql back-ends.


  • Added support for sql= to the unique constraints quasi-quoter so that users can specify the database names of the constraints.


  • DRY-ed up and exposed several util functions in Database.Persist.Sql.Util.
    • Upstream-ed updatePersistValue, mkUpdateText, and commaSeparated from Database.Persist.MySQL.
    • De-duplicated updatePersistValue from various Database.Persist.Sql.Orphan.* modules.
  • Batching enhancements to reduce db round-trips.
    • Added getMany and repsertMany for batched get and repsert.
    • Added putMany with a default/slow implementation. SqlBackend’s that support native UPSERT should override this for batching enhancements.
    • Updated insertEntityMany to replace slow looped usage with batched execution.
  • See #770


  • Switch from MonadBaseControl to MonadUnliftIO
  • Reapplies #723, which was reverted in version 2.7.3.

  • Improve error messages when failing to parse database results into Persistent records. #741
  • A handful of fromPersistField implementations called error instead of returning a Left Text. All of the implementations were changed to return Left. #741
  • Improve error message when a SQL insert fails with a custom primary key #757


  • Reverts #723, which generalized functions using the BackendCompatible class. These changes were an accidental breaking change.
  • Recommend the PersistDbSpecific docs if someone gets an error about converting from PersistDbSpecific


  • Many of the functions have been generalized using the BackendCompatible class. #723
    • This change was an accidental breaking change and was reverted in 2.7.3.
    • These change will be released in a future version of Persistent with a major version bump.
  • Add raw sql quasi quoters #717


  • Added an insertUniqueEntity function #718
  • Added BackendCompatible class #701


  • Fix upsert behavior #613
  • Atomic upsert query fixed for arithmatic operations #662
  • Haddock and test coverage improved for upsert


  • Fix edge case for \<-. [Nothing]
  • Introduce connMaxParams
  • Add ‘getJustEntity’ and ‘insertRecord’ convenience function
  • Minor Haddock improvment


  • Add connUpsertSql type for providing backend-specific upsert sql support.


  • read/write typeclass split
  • add insertOrGet convenience function to PersistUnique

  • Documentation updates #515


  • Workaround for side-exiting transformers in runSqlConn #516


  • PersistField instance for Natural
  • better oracle support in odbc


  • Add liftSqlPersistMPool function
  • support http-api-data for url serialization


  • Migration failure message with context
  • Fix insertKey for composite keys


  • Add a RawSql instance for Key. This allows selecting primary keys using functions like rawSql. #407
  • SqlBackend support for an optimized insertMany


Important! If persistent-template is not upgraded to you might need to make sure Int64 is in scope for your model declarations.

  • add showMigration function
  • explicitly use Int64 for foreign key references


Add dbIdColumnsEsc to Sql.Utils. Used in persistent-postgresql


  • Fix getBy with a primary key. #342


  • Break self-referencing cycles in the entity declarations


  • Error with Doubles without a decimal part #378
  • runSqlPool does not perform timeout checks.

  • One extra feature for #939: use logDebugN instead

Parse UTCTime in 8601 format #339

Support for monad-control 1.0