Photon.js is in Preview!
Limitations include missing features, limited performance and stability issues.
Read more

Build & ship faster with type-safe database access

Auto-generated database client (ORM*) for JavaScript/TypeScript based on your DB schema.

Quickstart
Follow Photon on GitHub
Follow Photon on GitHub

Explore the Photon API

Photon is based on modern JavaScript & TypeScript (ES6, ES7). Check out the full API documentation.

Reading
Writing
Field Selection
Schema

The API examples are based on a Prisma data model definition.

Explore the Photon API

Photon is based on modern JavaScript & TypeScript (ES6, ES7). Check out the full API documentation.

Lists & Single Objects

// Retrieve all posts
const allPosts: Post[] = await photon.posts.findMany()
Show the result
[
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: false,
    id: 'cjnymovq9s3hi0a51oz6rp83k',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Introducing the Analytical Engine'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: true,
    id: 'cjnymovqcs3hk0a51qfk40z0b',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Building General-Purpose Computers'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: false,
    id: 'cjnymovqjs3hm0a51hfdprde6',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'RESTful APIs Considered Harmful'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: true,
    id: 'cjnymovqls3ho0a51rhg7h2xv',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Why Algorithms are Awesome'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.127Z',
    published: false,
    id: 'cjnymovv7s3hu0a51j6he7hhs',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    title: 'Five Things You Didn't Know About Compilers'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.127Z',
    published: true,
    id: 'cjnymovvbs3hw0a51slwjkii7',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    title: 'GraphQL - The Query Language of the Future'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.127Z',
    published: true,
    id: 'cjnymovvds3hy0a51xtxyhyh2',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    title: 'Progamming with English Words'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.308Z',
    published: false,
    id: 'cjnymow08s3i70a51akud49tl',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    title: 'Working at Xerox PARC'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.308Z',
    published: true,
    id: 'cjnymow0as3i90a51muoz70zp',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    title: 'Introduction to VLSI Systems'
  }
]
// Retrieve user by ID
const userById: User = await photon.users.findOne({ where: { id : 54394 } })
Show the result
{
  id: 'cjnymovv3s3ht0a516fhmria8',
  name: 'Grace',
  email: 'grace@prisma.io'
}
// Retrieve user by email
const userByEmail: User = await photon.users.findOne({ where: { email : 'ada@prisma.io' } })
Show the result
{
  id: 'cjnymovq4s3hh0a51ghqhok2f',
  name: 'Ada',
  email: 'ada@prisma.io'
}

Fluent Relations API

// Retrieve the posts of a user
const postsByUser: Post[] = await photon
  .users
  .findOne({ where: { email: 'ada@prisma.io' }})
  .posts()
Show the result
[
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: false,
    id: 'cjnymovq9s3hi0a51oz6rp83k',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Introducing the Analytical Engine'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: true,
    id: 'cjnymovqcs3hk0a51qfk40z0b',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Building General-Purpose Computers'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: false,
    id: 'cjnymovqjs3hm0a51hfdprde6',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'RESTful APIs Considered Harmful'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: true,
    id: 'cjnymovqls3ho0a51rhg7h2xv',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Why Algorithms are Awesome'
  }
]
// Retrieve the categories of a post
const categoriesOfPost: Category[] = await photon
  .posts
  .findOne({ where: { id: 1 }})
  .categories()
Show the result
[
  {
    id: 'cjnymow0cs3ib0a517qntpuyf',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    text: 'I love this.'
  },
  {
    id: 'cjnymow0fs3ie0a51yres9ry8',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    text: 'Very interesting!'
  }
]
// Retrieve the posts of a user
const authorProfile: Category[] = await photon
  .posts
  .findOne({ where: { id: 1 } })
  .author()
  .profile()
Show the result
[
  {
    id: 'cjnymovvfs3i00a51q1mgzn6o',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    text: 'Great work!'
  },
  {
    id: 'cjnymow0cs3ib0a517qntpuyf',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    text: 'I love this.'
  }
]

Filtering & Sorting

// Retrieve all published posts about GraphQL or REST
const posts: Post[] = await photon.posts.findMany({
  where: {
    OR: [
      { title: { contains: 'GraphQL' } }, 
      { title: { contains: 'REST' } }
    ],
    published: true,
  },
  orderBy: { createdAt: 'asc' }
})
Show the result
[
  {
    updatedAt: '2018-11-01T13: 31: 14.127Z',
    published: true,
    id: 'cjnymovvbs3hw0a51slwjkii7',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    title: 'GraphQL - The Query Language of the Future'
  }
]
// Retrieve all posts of a particular user 
// that start with 'Hello'
const posts: Post[] = await photon.users.findOne({
  where: { email: 'ada@prisma.io' },
}).posts({
  where: {
    title: {
      startsWith: 'Hello'
    }
  }
})
Show the result
[
  {
    id: 'cjnymovvfs3i00a51q1mgzn6o',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    text: 'Great work!'
  }
]
// Sort posts alphabetically
const alphabeticPosts: Post[] = await photon.posts.findMany({
  orderBy: { title: 'asc' },
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: false,
  id: 'cjnymovq9s3hi0a51oz6rp83k',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Introducing the Analytical Engine'
},
{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: true,
  id: 'cjnymovqcs3hk0a51qfk40z0b',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Building General-Purpose Computers'
},
{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: false,
  id: 'cjnymovqjs3hm0a51hfdprde6',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'RESTful APIs Considered Harmful'
},
{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: true,
  id: 'cjnymovqls3ho0a51rhg7h2xv',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Why Algorithms are Awesome'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: false,
  id: 'cjnymovv7s3hu0a51j6he7hhs',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Five Things You Didn't Know About Compilers'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: false,
  id: 'cjnymow08s3i70a51akud49tl',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Working at Xerox PARC'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: true,
  id: 'cjnymow0as3i90a51muoz70zp',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Introduction to VLSI Systems'
}]

Pagination

// Retrieve the posts from position 6 to position 10
const paginatedPosts1: Post[] = await photon.posts.findMany({
  first: 5,
  skip: 5,
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: false,
  id: 'cjnymow08s3i70a51akud49tl',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Working at Xerox PARC'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: true,
  id: 'cjnymow0as3i90a51muoz70zp',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Introduction to VLSI Systems'
}]
// Retrieve the last 3 posts after having
// skipped 2 posts from the end of the list
const paginatedPosts2: Post[] = await photon.posts.findMany({
  last: 3,
  skip: 2,
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: false,
  id: 'cjnymovv7s3hu0a51j6he7hhs',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Five Things You Didn't Know About Compilers'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
}]
// Retrieve the first 5 posts after a cursor
const paginatedPosts3: Post[] = await photon.posts.findMany({
  first: 5,
  after: 43834, // represents an ID value
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: true,
  id: 'cjnymovqls3ho0a51rhg7h2xv',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Why Algorithms are Awesome'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: false,
  id: 'cjnymovv7s3hu0a51j6he7hhs',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Five Things You Didn't Know About Compilers'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: false,
  id: 'cjnymow08s3i70a51akud49tl',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Working at Xerox PARC'
}]
// Retrieve the last 5 posts before a cursor
const paginatedPosts4: Post[] = await photon.posts.findMany({
  last: 5,
  before: 10423, // represents an ID value
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: false,
  id: 'cjnymovqjs3hm0a51hfdprde6',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'RESTful APIs Considered Harmful'
},
{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: true,
  id: 'cjnymovqls3ho0a51rhg7h2xv',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Why Algorithms are Awesome'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: false,
  id: 'cjnymovv7s3hu0a51j6he7hhs',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Five Things You Didn't Know About Compilers'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
}]

Create, Update & Delete

// Create a new user
const newUser: User = await photon.users.create({
  data: {
    name: 'Alice',
    email: 'alice@prisma.io',
  },
})
Show the result
{
  id: 'cjnyr53gasxe00a51i4p2nx8n',
  name: 'Alice',
  email: 'alice@prisma.io',
  role: 'USER'
}
// Update an existing user
const updatedUser: User = await photon.users.update({
  data: { role: 'ADMIN' },
  where: { email: 'alice@prisma.io' },
})
Show the result
{
  id: 'cjnyr53gasxe00a51i4p2nx8n',
  name: 'Alice',
  email: 'alice@prisma.io',
  role: 'ADMIN'
}
// Delete an existing user
const deletedUser: User = await photon.users.delete({
  where: { email: 'alice@prisma.io' },
})
Show the result
{
  id: 'cjnyr53gasxe00a51i4p2nx8n',
  name: 'Alice',
  email: 'alice@prisma.io',
  role: 'ADMIN'
}

Nested Write

// Create a new user with two posts in a 
// single transaction
const newUser: User = await photon.users.create({
  data: {
    email: 'alice@prisma.io',
    posts: {
      create: [
        { title: 'Join the Prisma Slack on https://slack.prisma.io' },
        { title: 'Follow Prisma on Twitter' },
      ],
    },
  },
})
Show the result
{
  id: 'cjnyrgr97szhf0a51tjyz2e14', 
  name: null,
  email: 'alice@prisma.io'
}
// Change the author of a post in a single transaction
const updatedPost: Post = await photon.posts.update({
  where: { id: 5424 },
  data: {
    author: {
      connect: { email: 'alice@prisma.io' },
    },
  },
})
Show the result
{
  updatedAt: '2018-11-01T13:31:14.308Z', 
  published: true, 
  id: 'cjnymow0as3i90a51muoz70zp',
  createdAt: '2018-11-01T13:31:14.308Z', 
  title: 'Introduction to VLSI Systems'
}

Upsert

// Update existing user to grant admin rights 
// or create if don't exist yet
const upsertedUser: User = await photon.users.upsert({
  update: {
    role: 'ADMIN'
  },
  where: {
    email: 'alice@prisma.io'
  },
  create: {
    name: 'Alice',
    email: 'alice@prisma.io',
    role: 'ADMIN'
  }
})
Show the result
{
  id: 'cjnyrfmr9szcj0a51802wzot9',
  name: null,
  email: 'alice@prisma.io'
}

Batching

// Grant admin access to all users 
// who have a prisma.io-email
const updatedUsers: BatchPayload = await photon.users.updateMany({
  data: { role: 'ADMIN'},
  where: { email: { endsWith: '@prisma.io' } }
})
Show the result
{ count: 3 }
// Delete two users with specific email adresses 
// (emails that don't exist are silently ignored)
const deletedUsers: BatchPayload = await photon.users.deleteMany({
  where: {
    email: { in: ['alice@prisma.io', 'bob@prisma.io'] },
  }
})
Show the result
{ count: 1 }

Select Exclusively

// The returned post objects will only have the `title`, 
// `published` and `author` properties
const allPosts: Post[] = await photon.posts.findMany({
  select: {
    title: true,
    published: true
  }
})
Show the result
[
    {
      title: 'Join the Prisma Slack on https://slack.prisma.io',
      published: true
    },
    {
      title: 'Follow Prisma on Twitter',
      published: false
    }
  ]
// The returned user object will only have the `id` property
const newUser: User = await photon.users.create({
  data: {
    email: 'alice@prisma.io',
    posts: {
      create: [
        { title: 'Join the Prisma Slack on https://slack.prisma.io' },
        { title: 'Follow Prisma on Twitter' },
      ],
    },
  },
  select: { id: true }
})
Show the result
{
    id: 'cjnyt0bilt9tr0a511751giub'
  }

Include Additionally

// The returned posts objects will have all scalar fields of the `Post` model and additionally all the categories for each post
const allPosts: Post[] = await photon.posts.findMany({
  include: { categories: true }
})
Show the result
[
      {
          updatedAt: '2019-04-01T13: 31: 13.948Z',
          published: false,
          id: 'cjnymovq9s3hi0a51oz6rp83k',
          createdAt: '2019-11-01T13: 31: 13.948Z',
          title: 'Join the Prisma Slack on https://slack.prisma.io',
          categories: [{ id: "cjdisnmsp9smabxmcnkl", name: "slack" }]
       },
       {
          updatedAt: '2019-01-01T13: 31: 13.948Z',
          published: false,
          id: 'cjndncioqqpkdkkmxkkmd8dk',
          createdAt: '2018-11-01T13: 31: 13.948Z',
          title: 'Welcome to Prisma Day',
          categories: [
              { 
                id: "cjyq42xvk000001mrg87vdp1j", 
                name: "prisma-day" 
              },
              { 
                id: "cjyq43qau000201mrf8ucfzja", 
                name: "welcome" 
              }
           ]
       }
    ]
// The returned user object will have all scalar fields of the `User` model and additionally all the posts of that user
const newUser: User = await photon.users.create({
  data: {
    email: 'alice@prisma.io',
    posts: {
      create: [
        { title: 'Join the Prisma Slack on https://slack.prisma.io' },
        { title: 'Follow Prisma on Twitter' },
      ],
    },
  },
  include: { posts: true }
})
Show the result
{
      id: 'cjnymovv3s3ht0a516fhmria8',
      email: 'alice@prisma.io'
      posts: [
        {
          updatedAt: '2019-11-01T13: 31: 13.948Z',
          published: false,
          id: 'cjnymovq9s3hi0a51oz6rp83k',
          createdAt: '2018-11-01T13: 31: 13.948Z',
          title: 'Join the Prisma Slack on https://slack.prisma.io'
       },
       {
          updatedAt: '2019-11-01T13: 31: 13.948Z',
          published: false,
          id: 'cjnymovqcs3hk0a51qfk40z0b',
          createdAt: '2019-11-01T13: 31: 13.948Z',
          title: 'Follow Prisma on Twitter'
       }
      ]
    }

Lists & Single Objects

// Retrieve all posts
const allPosts: Post[] = await photon.posts.findMany()
Show the result
[
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: false,
    id: 'cjnymovq9s3hi0a51oz6rp83k',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Introducing the Analytical Engine'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: true,
    id: 'cjnymovqcs3hk0a51qfk40z0b',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Building General-Purpose Computers'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: false,
    id: 'cjnymovqjs3hm0a51hfdprde6',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'RESTful APIs Considered Harmful'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: true,
    id: 'cjnymovqls3ho0a51rhg7h2xv',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Why Algorithms are Awesome'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.127Z',
    published: false,
    id: 'cjnymovv7s3hu0a51j6he7hhs',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    title: 'Five Things You Didn't Know About Compilers'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.127Z',
    published: true,
    id: 'cjnymovvbs3hw0a51slwjkii7',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    title: 'GraphQL - The Query Language of the Future'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.127Z',
    published: true,
    id: 'cjnymovvds3hy0a51xtxyhyh2',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    title: 'Progamming with English Words'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.308Z',
    published: false,
    id: 'cjnymow08s3i70a51akud49tl',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    title: 'Working at Xerox PARC'
  },
  {
    updatedAt: '2018-11-01T13: 31: 14.308Z',
    published: true,
    id: 'cjnymow0as3i90a51muoz70zp',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    title: 'Introduction to VLSI Systems'
  }
]
// Retrieve user by ID
const userById: User = await photon.users.findOne({ where: { id : 54394 } })
Show the result
{
  id: 'cjnymovv3s3ht0a516fhmria8',
  name: 'Grace',
  email: 'grace@prisma.io'
}
// Retrieve user by email
const userByEmail: User = await photon.users.findOne({ where: { email : 'ada@prisma.io' } })
Show the result
{
  id: 'cjnymovq4s3hh0a51ghqhok2f',
  name: 'Ada',
  email: 'ada@prisma.io'
}

Fluent Relations API

// Retrieve the posts of a user
const postsByUser: Post[] = await photon
  .users
  .findOne({ where: { email: 'ada@prisma.io' }})
  .posts()
Show the result
[
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: false,
    id: 'cjnymovq9s3hi0a51oz6rp83k',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Introducing the Analytical Engine'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: true,
    id: 'cjnymovqcs3hk0a51qfk40z0b',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Building General-Purpose Computers'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: false,
    id: 'cjnymovqjs3hm0a51hfdprde6',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'RESTful APIs Considered Harmful'
  },
  {
    updatedAt: '2018-11-01T13: 31: 13.948Z',
    published: true,
    id: 'cjnymovqls3ho0a51rhg7h2xv',
    createdAt: '2018-11-01T13: 31: 13.948Z',
    title: 'Why Algorithms are Awesome'
  }
]
// Retrieve the categories of a post
const categoriesOfPost: Category[] = await photon
  .posts
  .findOne({ where: { id: 1 }})
  .categories()
Show the result
[
  {
    id: 'cjnymow0cs3ib0a517qntpuyf',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    text: 'I love this.'
  },
  {
    id: 'cjnymow0fs3ie0a51yres9ry8',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    text: 'Very interesting!'
  }
]
// Retrieve the posts of a user
const authorProfile: Category[] = await photon
  .posts
  .findOne({ where: { id: 1 } })
  .author()
  .profile()
Show the result
[
  {
    id: 'cjnymovvfs3i00a51q1mgzn6o',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    text: 'Great work!'
  },
  {
    id: 'cjnymow0cs3ib0a517qntpuyf',
    createdAt: '2018-11-01T13: 31: 14.308Z',
    text: 'I love this.'
  }
]

Filtering & Sorting

// Retrieve all published posts about GraphQL or REST
const posts: Post[] = await photon.posts.findMany({
  where: {
    OR: [
      { title: { contains: 'GraphQL' } }, 
      { title: { contains: 'REST' } }
    ],
    published: true,
  },
  orderBy: { createdAt: 'asc' }
})
Show the result
[
  {
    updatedAt: '2018-11-01T13: 31: 14.127Z',
    published: true,
    id: 'cjnymovvbs3hw0a51slwjkii7',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    title: 'GraphQL - The Query Language of the Future'
  }
]
// Retrieve all posts of a particular user 
// that start with 'Hello'
const posts: Post[] = await photon.users.findOne({
  where: { email: 'ada@prisma.io' },
}).posts({
  where: {
    title: {
      startsWith: 'Hello'
    }
  }
})
Show the result
[
  {
    id: 'cjnymovvfs3i00a51q1mgzn6o',
    createdAt: '2018-11-01T13: 31: 14.127Z',
    text: 'Great work!'
  }
]
// Sort posts alphabetically
const alphabeticPosts: Post[] = await photon.posts.findMany({
  orderBy: { title: 'asc' },
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: false,
  id: 'cjnymovq9s3hi0a51oz6rp83k',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Introducing the Analytical Engine'
},
{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: true,
  id: 'cjnymovqcs3hk0a51qfk40z0b',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Building General-Purpose Computers'
},
{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: false,
  id: 'cjnymovqjs3hm0a51hfdprde6',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'RESTful APIs Considered Harmful'
},
{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: true,
  id: 'cjnymovqls3ho0a51rhg7h2xv',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Why Algorithms are Awesome'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: false,
  id: 'cjnymovv7s3hu0a51j6he7hhs',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Five Things You Didn't Know About Compilers'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: false,
  id: 'cjnymow08s3i70a51akud49tl',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Working at Xerox PARC'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: true,
  id: 'cjnymow0as3i90a51muoz70zp',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Introduction to VLSI Systems'
}]

Pagination

// Retrieve the posts from position 6 to position 10
const paginatedPosts1: Post[] = await photon.posts.findMany({
  first: 5,
  skip: 5,
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: false,
  id: 'cjnymow08s3i70a51akud49tl',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Working at Xerox PARC'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: true,
  id: 'cjnymow0as3i90a51muoz70zp',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Introduction to VLSI Systems'
}]
// Retrieve the last 3 posts after having
// skipped 2 posts from the end of the list
const paginatedPosts2: Post[] = await photon.posts.findMany({
  last: 3,
  skip: 2,
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: false,
  id: 'cjnymovv7s3hu0a51j6he7hhs',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Five Things You Didn't Know About Compilers'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
}]
// Retrieve the first 5 posts after a cursor
const paginatedPosts3: Post[] = await photon.posts.findMany({
  first: 5,
  after: 43834, // represents an ID value
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: true,
  id: 'cjnymovqls3ho0a51rhg7h2xv',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Why Algorithms are Awesome'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: false,
  id: 'cjnymovv7s3hu0a51j6he7hhs',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Five Things You Didn't Know About Compilers'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
},
{
  updatedAt: '2018-11-01T13:31:14.308Z',
  published: false,
  id: 'cjnymow08s3i70a51akud49tl',
  createdAt: '2018-11-01T13:31:14.308Z',
  title: 'Working at Xerox PARC'
}]
// Retrieve the last 5 posts before a cursor
const paginatedPosts4: Post[] = await photon.posts.findMany({
  last: 5,
  before: 10423, // represents an ID value
})
Show the result
[{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: false,
  id: 'cjnymovqjs3hm0a51hfdprde6',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'RESTful APIs Considered Harmful'
},
{
  updatedAt: '2018-11-01T13:31:13.948Z',
  published: true,
  id: 'cjnymovqls3ho0a51rhg7h2xv',
  createdAt: '2018-11-01T13:31:13.948Z',
  title: 'Why Algorithms are Awesome'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: false,
  id: 'cjnymovv7s3hu0a51j6he7hhs',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Five Things You Didn't Know About Compilers'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvbs3hw0a51slwjkii7',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'GraphQL - The Query Language of the Future'
},
{
  updatedAt: '2018-11-01T13:31:14.127Z',
  published: true,
  id: 'cjnymovvds3hy0a51xtxyhyh2',
  createdAt: '2018-11-01T13:31:14.127Z',
  title: 'Progamming with English Words'
}]

Auto-generated & type-safe by default

Generated code that looks handwritten. Photon saves CRUD boilerplate and keeps your typings in sync with your database schema.

High performance & optimized queries

Photon is based on a high performance query engine that optimizes queries and ensures blazing fast database access.

Supports MySQL, Postgres & MongoDBSoon

Next to relational databases, Photon will soon support various kinds of data sources such as document and graph databases and even web APIs.

Designed for building APIs (GraphQL, REST, ...)

Save the boilerplate you’d have to write connect your API layer to the database. Photon supports GraphQL, REST, gRPC and many other use cases.

Replaces traditional ORMs & custom DALs

Photon challenges the status quo of ORMs with a new approach. Generate a type-safe data access API instead of writing brittle database queries.

Incremental adoption with existing database

When using Photon with an existing database, Photon will introspect the database schema and generate a custom database client for your app.

How Photon works

Connect your database

1

Introspect DB

Prisma analyses your database schema and generates a data model.

2
prisma
generate

Generate Client

Generate the Prisma client for your preferred programming language.

Build your app

Get started with Photon ...

Run $ npx prisma2 init and follow the interactive prompt to get started from scratch or with your existing database.
How does Photon fit into Prisma ecosystem?
$ npm install -g prisma2

$ prisma2 init
Created project.prisma
Run $ prisma2 generate to generate your Photon API

$ prisma2 generate
Generated Photon API based on project.prisma
You can import it with:
import { Photon } from '@generated/photon'

... or explore an example project

The example projects highlight practical use cases of Photon and are ready-to-run with just a few commands.

GraphQL API

Simple GraphQL server

REST API

Simple REST API with Express.JS

gRPC API

Simple gRPC API

FAQ

Can I still access my database directly (e.g. using raw SQL)?

While it's currently not possible to use Photon to directly access your database, this feature has a priority on our list and is one of the first things we are working on during the Preview period. You can track the progress of this feature here.

In the meanwhile, you can use Photon alongside other lightweight query builders such as knex.

Is Photon an ORM?

ORMs are typically object-oriented mapping layers that map classes to tables. A record is represented as an object that not only carries data but also implements various behaviours for storage, retrieval, serialization and deserialization of its own data, sometimes it also implements business/domain logic.

Photon acts more as a query builder returning plain objects with a focus on structural typing rather than rich object behavior.

Will Photon support more databases (and other data sources) in the future?

Yes. Photon is based on Prisma's query engine that can connect to any data source that provides a proper connector implementation. There will be built-in connectors such as the current ones for PostgreSQL, MySQL and SQLite. However, it's also possible to build your own connectors, more documentation on that topic will follow soon.

How can I see the generated queries that Photon sends to my database?

There will be rich query analytics for Photon soon. For now you can set the debug option to true when instanting your Photon instance. Learn more in the docs.

How do schema migrations work with Photon?

Photon is not opinionated on how exactly you migrate your database schema. You can keep your existing migration system and simply re-introspect your database schema after each migration to update Photon. Learn more in the docs.

You can also always use Lift to perform your migrations based on Prisma's declarative data model definition.

Is Photon production-ready? Should I start using it?

Photon is not yet production-ready, it has a number of severe limitations that don't make it suitable for production uses and heavy loads. You can track the progress of the release process on isprisma2ready.com.

While it shouldn't be used for critical applications yet, Photon is definitely in a usable state. You can help us accelerate the release process by using it and sharing your feedback with us.

Does Photon support GraphQL schema delegation and GraphQL binding?

GraphQL schema delegation connects two GraphQL schemas by passing the info object from a resolver of the first GraphQL schema to a resolver of the second GraphQL schema. Schema delegation also is the foundation for GraphQL binding.

Prisma 1 officially supports both schema delegation and GraphQL binding as it exposes a GraphQL CRUD API through the Prisma server . This API can be used to as foundation for an application-layer GraphQL API created with GraphQL binding.

With Prisma 2, Prisma's query engine doesn't expose a spec-compliant GraphQL endpoint any more, so usage of schema delegation and GraphQL binding with Prisma 2 is not officially supported. To build GraphQL servers with Prisma 2, be sure to check out GraphQL Nexus and its nexus-prisma integration. GraphQL Nexus provides a code-first and type-safe way to build GraphQL servers in a scalable way.

How to handle connection pooling for Photon.js in serverless environments?

The query engine that's powering the Photon.js API is maintaing a database connection pool. In serverless environments (or when running your application in containers, e.g. using Kubernetes), this connection pool might loose its effectiveness due to the infrastructure it's being deployed on. You can read more about this topic in the docs.

As of now, the recommended workaround is to use a tool like PgBouncer . We are further exploring some options, such as enabling a "DB proxy server" (e.g. using a specific generator that generates a Docker image to host Photon's query engine) that manages the connection pool for you (similar to the the Prisma 1 architecture).

Also note that there some cloud offerings start to have solutions for connection pooling out-of-the-box, such as AWS Aurora.