►
From YouTube: GraphQL Preloading
Description
No description was provided for this meeting.
If this is YOUR meeting, an easy way to fix this is to add a description to your video, wherever mtngs.io found it (probably YouTube).
B
Yeah
so
today,
I'm
going
to
talk
a
little
bit
about
performance
and
N,
plus
one
queries
in
graphql,
so
recently
I've
been
working
on
Branch
rules,
so
they're
moving
branches
to
this.
The
configuration
for
you
know
pushing
the
branches,
merging
branches
and
stuff
like
this
to
your
separate
page.
So
it's
easier
for
people
to
to
view
and
configure
and
that's
included
me
creating
a
whole
new
type
within
the
graphql
endpoint.
So
first
I'm
just
going
to
talk
a
bit
about
how
graphql
actually
works
so
graph.
C
B
The
type
you
specify
various
things
like
the
the
name
of
the
type-
if
you
look
at
this
one,
here's
the
project,
some
authorization,
stuff
I'll,
skip
over
this
one
out
and
then
Fields.
So
each
field
has
its
own
type.
You
know,
base
Fields
would
be
like
string,
integer
helium,
and
then
we
can
have
other
types
like
custom
types
that
we've
defined.
So,
for
example,
here
we
have
Branch
rules
which
is
the
type
one
here
is,
is
a
Project's
Branch
roadside.
So
this
is
one
that
I've
created
this
can
lead
to.
B
So
this
is
the
branchful
type,
which
also
has
its
own
Fields.
This
can
lead
to
interesting
queries
because
types
can
actually
loop
back
to
their
parents.
So,
for
example,
we
could
have
the
project
type
could
have
Branch
rules
and
then,
within
the
branch
rules
we
could
have
a
field
that
links
back
to
the
project,
and
this
would
allow
the
client
to
create
these.
B
You
know
looping
queries,
essentially
a
querying
for
the
same
data,
all
the
way
down
so.
B
To
kind
of
stifle
this
the
we
have
depth
which
configures
like
how
deep
somebody
can
query
down,
and
then
we
also
have
maximum
query
complexity,
so
the
complexity
specifies
you
know
how
how
how
much
of
a
performance
Tech
each
of
these
fields
is
gonna
course
to
our.
You
know
our
request.
So
by
default,
each
of
our
Fields
General
I,
think
by
default.
Each
of
them
has
a
complexity
of
one
and
then
our
schema
defines
the
maximum
complexity
for
the
whole
query.
B
So
if
you're
not
logged
in
a
defaults,
200
authenticated
as
250
for
admins,
it's
300..
So
you
know
this
would
mean
that
for
a
non-logged
in
user
they
can
query
200
fields
that
all
have
a
complexity
of
one.
However,
we
can
also
specify
higher
complexities.
So,
for
example,
if
we're
unable
to
preload
some
data-
or
you
know-
maybe
the
SQL
for
that
field-
just
isn't
very
performant-
we
can
add
a
complexity
configuration
to
the
field
itself.
B
B
Field
is
you
know
we
might
do
a
complexity
fire,
which
means
that
if
somebody
tries
to
query
this
field
it
bumps
up.
You
know
the
maximum
allowed
complexity
for
the
overall
query
that
will
allow
us
to
you
know,
prevent
you
know
essentially
Define
like
how
how
much
opponents
we
want
to
allow
on
orange
or
how
much
our
infrastructure
can
deliver.
B
B
So
that's
the
first
way
we
can
deal
with
some
of
these
fields
that
aren't
super
performance
and
and
then
the
second
thing
that
I
want
to
discuss
is
fetching
data.
So
often
when
we're
fetching
data,
we
we
can
introduce
n
plus
one
queries.
C
B
Resolve
these
n
plus
one
queries:
we
can
use
two
different
mechanisms,
so
we
have
batching
and
look
ahead.
So
that's
the
batch
later
allows
us
to
so.
If
I
just
show
you
this
class,
so
we've
got
this
user
resolver
here
and
so
maybe
first
I
should
discuss
what
a
resolver
is.
So
each
of
these
fields,
let's
go
back
to
yeah,
so
this
Branch
rules
fills
by
default.
What's
going
to
happen,
is
it's
going
to
cool
in
here
like
like
a
lot
of
serializers?
We
use
the
term
object.
B
So
object
is
the
the
objects,
that's
passed
into
this
type
and
we
would
call
Branch
rules
on
that
object.
But
sometimes
we
might
want
to
you
know
customize,
where
the
branch
rules
are
being
fetched
from
or
we
might
want
to
pass
in.
You
know
some
arguments
or
something.
B
So
in
that
case
we
can
create
a
resolver
which
is
actually
what's
defined
for
this
Branch
rules
field
and
then,
let's
go
back
to
the
batch
layers.
So.
B
Which
is
the
the
graphical
Ruby
method
that
is
called?
We
first
do
some
localization
and
then
we
check
if
if
the
ID
is
passed
and
we
just
look
out
from.
B
A
list
of
users
so
we're
going
to
pass
an
individual
username
to
this,
but
we
might,
we
might
be
trying
to
load
10
users
with
10
different
usernames,
so
rather
than
querying
for
them
one
by
one,
we
can
create
a
batch
of
usernames
and
then
once
we
have
all
of
those
usernames
within
this
batch
loader,
we
can
then
load
those
and
assign
them
through
the
username
value.
B
So
I
don't
understand
exactly
how
the
you
know,
mechanisms
within
this
work,
but
you
know
something
you
should
be
aware
of
that's
possible
and
in
some
situations
it
might
be
useful,
probably
tool
that
I've
currently
been
using
to
preload.
B
B
B
B
C
B
B
I,
just
reverse
it
and
took
a
screenshot
with
it,
and
this
module
should
not
be
included.
So
this
result
method
was
just
aliasing.
Essentially
you
know
where
we're
fetching
parietals
from
it's
actually
the
protective
branches
model
at
the
moment
in
the
future
that
will
change.
But
for
now
it's
that.
B
For
we
can
do
that
by
including
this
looks
ahead
module.
So
this
looks
ahead:
module
configures,
you
know
some
graphql
DSL
stuff,
so
it's
gonna.
It's
gonna
tell
the
graph
that
we
want
to
request
to.
A
C
B
And
then
it's
going
to
assign
the
look
ahead
to
this
actual
accessor
and
then
it's
going
to
call
result
with
look
ahead.
So
now
we
can
convert
our
branches
absorber
to
instead
of
the
resolve
method,
we're
going
to
use
resource
with
lookahead
and
we're
going
to
use
this
apply
lookahead
method
to
the
the
scope
that
we
want
to
resolve.
B
C
B
Place
is
this
unconditional
includes
method,
so
if
we
take
a
look
at
what
that's
actually
doing
by
default,
this
is
just
going
to
return
an
empty
array.
However,
if
we
override
this
in
our
resolver
class,
we
can
tell
the
result
that
we
always
wants
to
preload
some
of
the
associations
for
that
that
model.
So,
for
example,
here,
if
we
just
add
unconditional,
includes
we
can
say,
regardless
of
what
the
user
has
requested,
we're
always
going
to
preload
the
approval
rules
and
the
users
and
groups
nested
within
that.
B
And
then
we
can
do
some
conditional
stuff,
so
sometimes
we
may
want
to
preload
based
on
what
the
user
has
requested.
So
here
we
can
see
our
preload
function.
Method
is
going
to
return
this
this
hash,
so
the
key
here
is
going
to
be
we're
going
to
look
in
the
look
ahead
to
see
if
this
key
has
been
requested.
So
I'm
not
sure.
If
I
put
an
example
now
I
didn't,
maybe
I
can
see.
Maybe
it's
not
worth
it.
B
This
is
actually
going
to
do.
Is
it's
going
to
go
into
it's
going
to
look
at
the
look
ahead
and
it's
going
to
say:
does
this
select
approval
rules
and
if
it
has
selected
approval
rules,
it's
going
to
try
and
preload
approval
project
rules,
users,
group
users,
and
then
it's
going
to
do
the
same
for
external
status
checks.
If
this
has
been
requested,
then
we're
going
to
preload
the
external
status
checks.
B
So
that's,
you
know
quite
straightforward.
It's
quite
easy
to
understand
and
allows
us
to
preload
data
very
simply
without
actually
interacting
with
the
look
ahead
ourselves.
C
B
Is
nested
preloads,
which
essentially
behaves
exactly
the
same
way
as
the
preloaded
method,
except
it's
going
to
the
look
ahead
keys.
Are
you
know
not
just
the
top
level?
It's
also
the
next
level
down
as
well.
So,
for
example,
if
we,
if.
C
B
B
We
defined
this
big
external
status
checks
we're
gonna.
If
external
status
checks
is
being
requested,
we
will
preload
the
external
status
checks.
So
if
the
user
has
submitted
this
graphql
query,
we
can
see
external
status
checks
were
requested,
so
that
will
be
loaded.
However,
nested
preload
is
it's
going
to
look
two
levels
deep?
So
if
we
request
Branch
protection
and
within
that
we've
also
requested
merge
access
levels,
then
we're
going
to
preload
the
user.
B
This
would
not
preload
the
merge
access
level
user,
even
though
we've
requested
the
merge
access
levels.
So
you
see
here,
we've
got
projects
branches
within
the
branches
resolver,
but
we're
checking
if
Branch
protection
is
being
requested
and
then,
if
merge
access
levels
are
being
protected,
then
we'll
load,
the
user
and,
however,
with
it
sorry
that's
slightly
wrong.
This
example
is
actually
slightly
wrong,
but
I
think
you
should.
Hopefully
you
understand
this
so
in.
C
B
The
merge
access
levels,
but
we
haven't
requested
the
user
from
that
merge
access
level.
In
the
second
example
here
we
have
requested
the
user
and
their
name,
and
so
our
conditional
logic
would
check.
You
know,
check
that,
and
essentially
it
would
only
it.
B
Are
built
into
the
looks
ahead,
module
and
they're?
You
know
they're
quite
self-explanatory
and
easy
to
use,
and
then
we
have
another
situation
where
you
might
want
to
do
some
more
complex
checks
and
where
these
preloaded
and
nested
preloaded
methods
don't
quite
fit
our
needs
so,
for
example,
with
Branch
Wheels
branches
set
up
quite
strangely
at
the
moment,
because
we
don't
actually
have
a
branch
rule
model.
B
So
when
you
query
a
branch
rule,
there's
also
a
field
inside
that
called
Branch
protection,
which
is
actually
the
branch
Rule
and
the
branch
protection
are
currently
the
same
object,
which
means
we
need
to
use
this
nested
preloads.
So
first,
we
want
to
check
if
Branch
protection
has
been
requested,
even
though
it's
the
same
object,
and
then
we
want
to
check
if
the
merge
access
levels
are
requested
within
that
node
and
once
we
do
that,
we
also
then
wanted
to
check
if
the
group
or
the
user
has
been
requested.
B
So
we
can
see
here
in
our
nested
prelays
we're
supplying
the
branch
reflection
key
and
then
within
that
the
merge
access
level
is
key
deeper
than
that
we,
the
the
current,
looks
ahead.
Module.
Doesn't
allow
us
to
go
deeper
than
that,
so
what
what
I've
actually
done
here
is
manually
built
the
list
of
preloads,
so
I'm
going
to
check
if
see
online
24
we've
got
access
level,
preloads,
four
and
we're
going
to
find
the
access
levels
look
ahead.
B
So
that's
at
the
bottom
here,
so
we've
got
the
the
the
look
ahead
at
the
at
the
root
of
the
query:
we're
going
to
check
if
it
selects
Branch
protections
and
then
we're
going
to
select
the
access
level.
B
This
could
be
either
merge,
push
or
unprotected
access
levels
and
then
we're
gonna
fetch
the
node
selection.
So
it
could
either
be
edges,
node
or
just
nodes,
and
that's
going
to
return
to
look
ahead
specifically
for
the
access
to
level
part
of
the
query
and
then
we
can
detect
within
that
look
ahead.
If.
C
B
Group
has
been
selected
or
the
user
has
been
selected,
and
then
we
can
manually
build
these
these
preloads.
So
you
know
here
we're
just
loading.
The
sound
will
provide
on
the
routes
and
the
parent
and
for
the
users
we
we
preload
their
groups
and
their
projects
yeah.
So
that's
a
bit
more
complex
and
gives
us
a
lot
more
flexibility,
but
also
means
that
you
know
we
need
to
do
a
lot
more
of
the
work
ourselves.
B
B
End
of
my
presentation,
if
anyone's
got
any
questions,
fire
away.
D
C
B
B
E
E
Yeah
I
had
a
question
about
the
the
complexity
thing
so.
B
E
B
So
the
depth,
currently
the
depth
of
how
far
you
can
queries,
is
over
15
or
20.,
but
you
could
you
know
the
the
width
of
that
the
width
of
each
node
is
is
currently
unlimited.
I
mean
you
reached
a
complexity
limit
right,
so
you.
B
Yeah
so
but
you
can,
you
see
graphical
yep,
yes,.
A
B
Okay,
so,
for
example,
here,
like
the
you
know,
the
the
query
is
is
for
the
project
and
that
project
has
multiple
fields
on
there
like,
for
example,
job
by
default.
Each
field
will
be
one,
so
we
we
could
have.
You
know
300
different
fields,
all
the
way
down
here.
Okay
or
you
could
you
know
you
could
have
like
one
one
field
like
branchfuls
and
within
that
have
another
299
fails
yeah.
That.
B
E
B
So
this
is,
you
know
this
is
for
us,
so
we
can't
actually
create
that
data,
and
you
know
using
this
batch
loading
strategy-
oh
yeah
yeah,
and
so
instead
of
doing
the
query
multiple
times,
we
can
just
return
the
same
object.
However,
the
complexity,
we
can
also
use
the
complexity
to
kind
of
prevent
people
from
from
doing
those
queries,
yeah,
okay,.
B
A
D
A
Guess
I
guess
yeah,
it's
my
mine
is
a
bit
blown,
but
one
thing
because
going
back
to
the
original
premise
of
this
talk
right,
like
it
seems,
I'm
wondering
how
it
seems
like
to
me
that
everything
would
generate
an
N
plus
one
practically
in
graphql.
Unless
is
the
whole.
Is
the
schema
all
loaded
into
memory
and
doesn't
need
to
touch
the
database?
I
mean
how
do
we
avoid
multiple
M,
plus
ones,
I
guess.
B
Yeah,
it's
so
I
haven't
verified
this
yet,
but
I'm
feeling
that
quite
a
few
other
endpoints
do
actually
have
a
lot
of
n
plus
ones.
Oh
yeah,
so
something
else
I
forgot
to
show
you
was
the
actual
tests.
B
Yeah
so
I
mean
it's
a
schema
and
then
based
on
the
the
query,
that's
you
know
sent
we
build
a
list
of
queries
that
we
need
to
fire
and
then
the
environment
and
the
data
I'm
not
exactly
sure
how
it
works
under
the
hood.
Okay,
there's
there's.
Definitely
a
lot
of
room
for
n,
plus
one
queries
to
to
happen.
If
you're,
not
careful.
C
E
Checked
the
the
implementation
of
the
loaders
back
back
in
with
JavaScript
again,
it's
actually
not
super
complicated.
It's
just
a
hash
list
that
they
filled
up
with
the
the
parameters
that
you
give
them,
and
if
the
parameters
are
the
same,
they
they
don't
recreate
or
they
don't
append
again
the
same
values
and.
B
Could
you
could
pre-load
all
the
data
from
the
root
level
so
like
if
we're
querying
from
projects
and
then
inside
that
the
users
within
the
project
or
whatever
we
could
from
the
root
level?
We
could
say:
okay,
what's
been
requested
and
preload
everything,
but
sometimes
it
might
actually
be
more
performant
to
split
those
queries
up
like
maybe
maybe,
like
you
know,
query
for
the
project
and
preloading
all
users
is,
you
know
terrible.
B
B
Is
n,
plus
one
spec
they're
actually
quite
simple,
to
build?
However,
there
are
a
couple
of
gotchans
which
includes
one
that
I
struggled
with
this,
which
was
or
last
week,
which
drove
me
a
little
bit
crazy,
which
is
use
the
tracking.
So
you
devise
has
some
methods
to
track
when
the
user's
logged
in
tracks
their
IP
last
logged
in
at
and
stuff
like
that.
B
So
you
know
so
I've
added
some
some
logic
so
ask
about
how
to
see
spiders,
I'm,
not
sure
I'm,
sure
everyone's
aware
of
this
stuff,
but
like
allow
users
to
receive
learn
return
whatever
so
I
just
added
a
shared
context
that
essentially
just
turns
all
of
that
stuff
off,
but
yeah
the
the
basics
for
doing
an
M
plus
one
spec.
Is
you
set
up
a
control
with
an
active
action,
active
record,
query
recorder:
you
you
submit
the
request.
B
Once
some
people
have
been
checking
graphq
areas,
I'm,
seeing
as
some
people
don't
it's
a
bit.
You
know
there's
a
bit
of
a
not
not
so
much
of
a
strong
consensus
on
how
to
do
these
I
found
that
it,
it's
probably
a
good
idea
to
add.
B
You
know
this
this
method,
because
sometimes
you'll
actually
get
errors
back
and
then
you
don't
know
if
you're
checking
the
correct
queries
essentially
and
then
you
want
to
create
another
record
so
that
you,
you
would
create
an
N
plus
one
if
there's
one
present
and
then
submit
the
query
again,
and
this
is
actually
in
the
wrong
direction.
People
there
yeah
and
then
submit
the
query
again
and
we've
got
this
custom
aspect.
Matcher
exceed
all
query
limit,
which
basically
checks.
If
this
control
up
here
has
more
queries,
less
queries
than
this
one.
B
So
it's
quite
a
simple
test
to
configure,
but
yeah
there's
a
couple
of
issues
that
you,
you
have
to
be
aware
of.
I.
Think
like.
C
Yeah,
just
a
quick
note
regarding
the
test.
Yes,
sometimes
it
makes
makes
sense
to
call
a
single
like
critical
query
before
even
recording,
of
course,
yeah
like
a
warm
up.
B
Yeah,
so
this
yeah
so
recently
I'm
not
sure
how
many
people
saw
her,
but
Jesse
I
can't
remember
her
last
name,
but
she
mentioned
this
in
slack
that
she's
created
a
new
she's
trying
to
create
a
new
guideline.
Essentially,
so
you
should
turn
off
the
sgr
query
cache
and
then
your
very
recorded
should
also
skip
cash.
False
and
doing
this
prevents
any
of
the
cached
yeah
essentially
means
you
don't
need
to
warm
up
the
cache,
so
we
we
should
be
able
to.
Theoretically,
we
should
be
able
to
remove
those
initial
queries.