diff --git a/CHANGELOG.md b/CHANGELOG.md
index 009b8c57dd2..34563322234 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,9 @@
   [@PowerKiKi](https://github.com/PowerKiKi) in [#3692](https://github.com/apollographql/apollo-client/pull/3692)
 - Corrected `ApolloClient.queryManager` typing as it may be `undefined`.  <br/>
   [@danilobuerger](https://github.com/danilobuerger) in [#3661](https://github.com/apollographql/apollo-client/pull/3661)
+- Make sure using a `no-cache` fetch policy with subscriptions prevents data
+  from being cached.  <br/>
+  [@hwillson](https://github.com/hwillson) in [#3773](https://github.com/apollographql/apollo-client/pull/3773)
 - Documentation updates.  <br/>
   [@hwillson](https://github.com/hwillson) in [#3750](https://github.com/apollographql/apollo-client/pull/3750)  <br/>
   [@hwillson](https://github.com/hwillson) in [#3754](https://github.com/apollographql/apollo-client/pull/3754)  <br/>
diff --git a/packages/apollo-cache-inmemory/src/mapCache.ts b/packages/apollo-cache-inmemory/src/mapCache.ts
index f8ac715e88b..35c00823d10 100644
--- a/packages/apollo-cache-inmemory/src/mapCache.ts
+++ b/packages/apollo-cache-inmemory/src/mapCache.ts
@@ -5,22 +5,28 @@ import { NormalizedCache, NormalizedCacheObject, StoreObject } from './types';
  * Note that you need a polyfill for Object.entries for this to work.
  */
 export class MapCache implements NormalizedCache {
-  cache: Map<string, StoreObject>;
+  private cache: Map<string, StoreObject>;
+
   constructor(data: NormalizedCacheObject = {}) {
     this.cache = new Map(Object.entries(data));
   }
-  get(dataId: string): StoreObject {
+
+  public get(dataId: string): StoreObject {
     return this.cache.get(`${dataId}`);
   }
-  set(dataId: string, value: StoreObject): void {
+
+  public set(dataId: string, value: StoreObject): void {
     this.cache.set(`${dataId}`, value);
   }
-  delete(dataId: string): void {
+
+  public delete(dataId: string): void {
     this.cache.delete(`${dataId}`);
   }
-  clear(): void {
+
+  public clear(): void {
     return this.cache.clear();
   }
+
   public toObject(): NormalizedCacheObject {
     const obj: NormalizedCacheObject = {};
     this.cache.forEach((dataId, key) => {
@@ -28,6 +34,7 @@ export class MapCache implements NormalizedCache {
     });
     return obj;
   }
+
   public replace(newData: NormalizedCacheObject): void {
     this.cache.clear();
     Object.entries(newData).forEach(([dataId, value]) =>
diff --git a/packages/apollo-cache-inmemory/src/recordingCache.ts b/packages/apollo-cache-inmemory/src/recordingCache.ts
index 518fbae6ea3..a71249ef8cb 100644
--- a/packages/apollo-cache-inmemory/src/recordingCache.ts
+++ b/packages/apollo-cache-inmemory/src/recordingCache.ts
@@ -1,10 +1,10 @@
 import { NormalizedCache, NormalizedCacheObject, StoreObject } from './types';
 
 export class RecordingCache implements NormalizedCache {
-  constructor(private readonly data: NormalizedCacheObject = {}) {}
-
   private recordedData: NormalizedCacheObject = {};
 
+  constructor(private readonly data: NormalizedCacheObject = {}) {}
+
   public record(
     transaction: (recordingCache: RecordingCache) => void,
   ): NormalizedCacheObject {
diff --git a/packages/apollo-client/src/__tests__/graphqlSubscriptions.ts b/packages/apollo-client/src/__tests__/graphqlSubscriptions.ts
index c5bc1cbefc9..89a70da8aff 100644
--- a/packages/apollo-client/src/__tests__/graphqlSubscriptions.ts
+++ b/packages/apollo-client/src/__tests__/graphqlSubscriptions.ts
@@ -1,190 +1,212 @@
-import gql from 'graphql-tag';
-import { InMemoryCache } from 'apollo-cache-inmemory';
-
-import { mockObservableLink, MockedSubscription } from '../__mocks__/mockLinks';
-
-import ApolloClient from '../';
-
-import { QueryManager } from '../core/QueryManager';
-import { DataStore } from '../data/store';
-
-describe('GraphQL Subscriptions', () => {
-  const results = [
-    'Dahivat Pandya',
-    'Vyacheslav Kim',
-    'Changping Chen',
-    'Amanda Liu',
-  ].map(name => ({ result: { data: { user: { name } } }, delay: 10 }));
-
-  let sub1: MockedSubscription;
-  let options: any;
-  let defaultOptions: any;
-  let defaultSub1: MockedSubscription;
-  beforeEach(() => {
-    sub1 = {
-      request: {
-        query: gql`
-          subscription UserInfo($name: String) {
-            user(name: $name) {
-              name
-            }
-          }
-        `,
-        variables: {
-          name: 'Changping Chen',
-        },
-      },
-    };
-
-    options = {
-      query: gql`
-        subscription UserInfo($name: String) {
-          user(name: $name) {
-            name
-          }
-        }
-      `,
-      variables: {
-        name: 'Changping Chen',
-      },
-    };
-
-    defaultSub1 = {
-      request: {
-        query: gql`
-          subscription UserInfo($name: String = "Changping Chen") {
-            user(name: $name) {
-              name
-            }
-          }
-        `,
-        variables: {
-          name: 'Changping Chen',
-        },
-      },
-    };
-
-    defaultOptions = {
-      query: gql`
-        subscription UserInfo($name: String = "Changping Chen") {
-          user(name: $name) {
-            name
-          }
-        }
-      `,
-    };
-  });
-
-  it('should start a subscription on network interface and unsubscribe', done => {
-    const link = mockObservableLink(defaultSub1);
-    // This test calls directly through Apollo Client
-    const client = new ApolloClient({
-      link,
-      cache: new InMemoryCache({ addTypename: false }),
-    });
-
-    let count = 0;
-    const sub = client.subscribe(defaultOptions).subscribe({
-      next(result) {
-        count++;
-        expect(result).toEqual(results[0].result);
-
-        // Test unsubscribing
-        if (count > 1) {
-          throw new Error('next fired after unsubscribing');
-        }
-        sub.unsubscribe();
-        done();
-      },
-    });
-
-    link.simulateResult(results[0]);
-  });
-
-  it('should subscribe with default values', done => {
-    const link = mockObservableLink(sub1);
-    // This test calls directly through Apollo Client
-    const client = new ApolloClient({
-      link,
-      cache: new InMemoryCache({ addTypename: false }),
-    });
-
-    let count = 0;
-    const sub = client.subscribe(options).subscribe({
-      next(result) {
-        expect(result).toEqual(results[0].result);
-
-        // Test unsubscribing
-        if (count > 1) {
-          throw new Error('next fired after unsubscribing');
-        }
-        sub.unsubscribe();
-
-        done();
-      },
-    });
-
-    link.simulateResult(results[0]);
-  });
-
-  it('should multiplex subscriptions', done => {
-    const link = mockObservableLink(sub1);
-    const queryManager = new QueryManager({
-      link,
-      store: new DataStore(new InMemoryCache({ addTypename: false })),
-    });
-
-    const obs = queryManager.startGraphQLSubscription(options);
-
-    let counter = 0;
-
-    // tslint:disable-next-line
-    obs.subscribe({
-      next(result) {
-        expect(result).toEqual(results[0].result);
-        counter++;
-        if (counter === 2) {
-          done();
-        }
-      },
-    }) as any;
-
-    // Subscribe again. Should also receive the same result.
-    // tslint:disable-next-line
-    obs.subscribe({
-      next(result) {
-        expect(result).toEqual(results[0].result);
-        counter++;
-        if (counter === 2) {
-          done();
-        }
-      },
-    }) as any;
-
-    link.simulateResult(results[0]);
-  });
-
-  it('should receive multiple results for a subscription', done => {
-    const link = mockObservableLink(sub1);
-    let numResults = 0;
-    const queryManager = new QueryManager({
-      link,
-      store: new DataStore(new InMemoryCache({ addTypename: false })),
-    });
-
-    // tslint:disable-next-line
-    queryManager.startGraphQLSubscription(options).subscribe({
-      next(result) {
-        expect(result).toEqual(results[numResults].result);
-        numResults++;
-        if (numResults === 4) {
-          done();
-        }
-      },
-    }) as any;
-
-    for (let i = 0; i < 4; i++) {
-      link.simulateResult(results[i]);
-    }
-  });
-});
+import gql from 'graphql-tag';
+import { InMemoryCache } from 'apollo-cache-inmemory';
+
+import { mockObservableLink, MockedSubscription } from '../__mocks__/mockLinks';
+
+import ApolloClient from '../';
+
+import { QueryManager } from '../core/QueryManager';
+import { DataStore } from '../data/store';
+
+describe('GraphQL Subscriptions', () => {
+  const results = [
+    'Dahivat Pandya',
+    'Vyacheslav Kim',
+    'Changping Chen',
+    'Amanda Liu',
+  ].map(name => ({ result: { data: { user: { name } } }, delay: 10 }));
+
+  let sub1: MockedSubscription;
+  let options: any;
+  let defaultOptions: any;
+  let defaultSub1: MockedSubscription;
+  beforeEach(() => {
+    sub1 = {
+      request: {
+        query: gql`
+          subscription UserInfo($name: String) {
+            user(name: $name) {
+              name
+            }
+          }
+        `,
+        variables: {
+          name: 'Changping Chen',
+        },
+      },
+    };
+
+    options = {
+      query: gql`
+        subscription UserInfo($name: String) {
+          user(name: $name) {
+            name
+          }
+        }
+      `,
+      variables: {
+        name: 'Changping Chen',
+      },
+    };
+
+    defaultSub1 = {
+      request: {
+        query: gql`
+          subscription UserInfo($name: String = "Changping Chen") {
+            user(name: $name) {
+              name
+            }
+          }
+        `,
+        variables: {
+          name: 'Changping Chen',
+        },
+      },
+    };
+
+    defaultOptions = {
+      query: gql`
+        subscription UserInfo($name: String = "Changping Chen") {
+          user(name: $name) {
+            name
+          }
+        }
+      `,
+    };
+  });
+
+  it('should start a subscription on network interface and unsubscribe', done => {
+    const link = mockObservableLink(defaultSub1);
+    // This test calls directly through Apollo Client
+    const client = new ApolloClient({
+      link,
+      cache: new InMemoryCache({ addTypename: false }),
+    });
+
+    let count = 0;
+    const sub = client.subscribe(defaultOptions).subscribe({
+      next(result) {
+        count++;
+        expect(result).toEqual(results[0].result);
+
+        // Test unsubscribing
+        if (count > 1) {
+          throw new Error('next fired after unsubscribing');
+        }
+        sub.unsubscribe();
+        done();
+      },
+    });
+
+    link.simulateResult(results[0]);
+  });
+
+  it('should subscribe with default values', done => {
+    const link = mockObservableLink(sub1);
+    // This test calls directly through Apollo Client
+    const client = new ApolloClient({
+      link,
+      cache: new InMemoryCache({ addTypename: false }),
+    });
+
+    let count = 0;
+    const sub = client.subscribe(options).subscribe({
+      next(result) {
+        expect(result).toEqual(results[0].result);
+
+        // Test unsubscribing
+        if (count > 1) {
+          throw new Error('next fired after unsubscribing');
+        }
+        sub.unsubscribe();
+
+        done();
+      },
+    });
+
+    link.simulateResult(results[0]);
+  });
+
+  it('should multiplex subscriptions', done => {
+    const link = mockObservableLink(sub1);
+    const queryManager = new QueryManager({
+      link,
+      store: new DataStore(new InMemoryCache({ addTypename: false })),
+    });
+
+    const obs = queryManager.startGraphQLSubscription(options);
+
+    let counter = 0;
+
+    // tslint:disable-next-line
+    obs.subscribe({
+      next(result) {
+        expect(result).toEqual(results[0].result);
+        counter++;
+        if (counter === 2) {
+          done();
+        }
+      },
+    }) as any;
+
+    // Subscribe again. Should also receive the same result.
+    // tslint:disable-next-line
+    obs.subscribe({
+      next(result) {
+        expect(result).toEqual(results[0].result);
+        counter++;
+        if (counter === 2) {
+          done();
+        }
+      },
+    }) as any;
+
+    link.simulateResult(results[0]);
+  });
+
+  it('should receive multiple results for a subscription', done => {
+    const link = mockObservableLink(sub1);
+    let numResults = 0;
+    const queryManager = new QueryManager({
+      link,
+      store: new DataStore(new InMemoryCache({ addTypename: false })),
+    });
+
+    // tslint:disable-next-line
+    queryManager.startGraphQLSubscription(options).subscribe({
+      next(result) {
+        expect(result).toEqual(results[numResults].result);
+        numResults++;
+        if (numResults === 4) {
+          done();
+        }
+      },
+    }) as any;
+
+    for (let i = 0; i < 4; i++) {
+      link.simulateResult(results[i]);
+    }
+  });
+
+  it('should not cache subscription data if a `no-cache` fetch policy is used', done => {
+    const link = mockObservableLink(sub1);
+    const cache = new InMemoryCache({ addTypename: false });
+    const client = new ApolloClient({
+      link,
+      cache,
+    });
+
+    expect(cache.extract()).toEqual({});
+
+    options.fetchPolicy = 'no-cache';
+    const sub = client.subscribe(options).subscribe({
+      next() {
+        expect(cache.extract()).toEqual({});
+        sub.unsubscribe();
+        done();
+      },
+    });
+
+    link.simulateResult(results[0]);
+  });
+});
diff --git a/packages/apollo-client/src/core/QueryManager.ts b/packages/apollo-client/src/core/QueryManager.ts
index ff0fe886912..df885e0c195 100644
--- a/packages/apollo-client/src/core/QueryManager.ts
+++ b/packages/apollo-client/src/core/QueryManager.ts
@@ -859,29 +859,6 @@ export class QueryManager<TStore> {
     });
   }
 
-  private getObservableQueryPromises(
-    includeStandby?: boolean,
-  ): Promise<ApolloQueryResult<any>>[] {
-    const observableQueryPromises: Promise<ApolloQueryResult<any>>[] = [];
-    this.queries.forEach(({ observableQuery }, queryId) => {
-      if (!observableQuery) return;
-      const fetchPolicy = observableQuery.options.fetchPolicy;
-
-      observableQuery.resetLastResults();
-      if (
-        fetchPolicy !== 'cache-only' &&
-        (includeStandby || fetchPolicy !== 'standby')
-      ) {
-        observableQueryPromises.push(observableQuery.refetch());
-      }
-
-      this.setQuery(queryId, () => ({ newData: null }));
-      this.invalidate(true, queryId);
-    });
-
-    return observableQueryPromises;
-  }
-
   public reFetchObservableQueries(
     includeStandby?: boolean,
   ): Promise<ApolloQueryResult<any>[]> {
@@ -913,6 +890,9 @@ export class QueryManager<TStore> {
     options: SubscriptionOptions,
   ): Observable<any> {
     const { query } = options;
+    const isCacheEnabled = !(
+      options.fetchPolicy && options.fetchPolicy === 'no-cache'
+    );
     const cache = this.dataStore.getCache();
     let transformedDoc = cache.transformDocument(query);
 
@@ -928,20 +908,25 @@ export class QueryManager<TStore> {
     return new Observable(observer => {
       observers.push(observer);
 
-      // If this is the first observer, actually initiate the network subscription
+      // If this is the first observer, actually initiate the network
+      // subscription.
       if (observers.length === 1) {
         const handler = {
           next: (result: FetchResult) => {
-            this.dataStore.markSubscriptionResult(
-              result,
-              transformedDoc,
-              variables,
-            );
-            this.broadcastQueries();
+            if (isCacheEnabled) {
+              this.dataStore.markSubscriptionResult(
+                result,
+                transformedDoc,
+                variables,
+              );
+              this.broadcastQueries();
+            }
 
-            // It's slightly awkward that the data for subscriptions doesn't come from the store.
+            // It's slightly awkward that the data for subscriptions doesn't
+            // come from the store.
             observers.forEach(obs => {
-              // XXX I'd prefer a different way to handle errors for subscriptions
+              // XXX I'd prefer a different way to handle errors for
+              // subscriptions.
               if (obs.next) obs.next(result);
             });
           },
@@ -1055,6 +1040,29 @@ export class QueryManager<TStore> {
     });
   }
 
+  private getObservableQueryPromises(
+    includeStandby?: boolean,
+  ): Promise<ApolloQueryResult<any>>[] {
+    const observableQueryPromises: Promise<ApolloQueryResult<any>>[] = [];
+    this.queries.forEach(({ observableQuery }, queryId) => {
+      if (!observableQuery) return;
+      const fetchPolicy = observableQuery.options.fetchPolicy;
+
+      observableQuery.resetLastResults();
+      if (
+        fetchPolicy !== 'cache-only' &&
+        (includeStandby || fetchPolicy !== 'standby')
+      ) {
+        observableQueryPromises.push(observableQuery.refetch());
+      }
+
+      this.setQuery(queryId, () => ({ newData: null }));
+      this.invalidate(true, queryId);
+    });
+
+    return observableQueryPromises;
+  }
+
   // Takes a request id, query id, a query document and information associated with the query
   // and send it to the network interface. Returns
   // a promise for the result associated with that request.
diff --git a/packages/apollo-client/src/core/watchQueryOptions.ts b/packages/apollo-client/src/core/watchQueryOptions.ts
index addf271d707..441d00d0e99 100644
--- a/packages/apollo-client/src/core/watchQueryOptions.ts
+++ b/packages/apollo-client/src/core/watchQueryOptions.ts
@@ -143,6 +143,11 @@ export interface SubscriptionOptions<TVariables = OperationVariables> {
    * GraphQL document to that variable's value.
    */
   variables?: TVariables;
+
+  /**
+   * Specifies the {@link FetchPolicy} to be used for this subscription.
+   */
+  fetchPolicy?: FetchPolicy;
 }
 
 export type RefetchQueryDescription = Array<string | PureQueryOptions>;
diff --git a/packages/apollo-client/src/util/subscribeAndCount.ts b/packages/apollo-client/src/util/subscribeAndCount.ts
index 23685547eef..f38872b0a3c 100644
--- a/packages/apollo-client/src/util/subscribeAndCount.ts
+++ b/packages/apollo-client/src/util/subscribeAndCount.ts
@@ -3,7 +3,7 @@ import { ApolloQueryResult } from '../../src/core/types';
 import { Subscription } from '../../src/util/Observable';
 
 export default function subscribeAndCount(
-  done: (...args) => void,
+  done: jest.DoneCallback,
   observable: ObservableQuery<any>,
   cb: (handleCount: number, result: ApolloQueryResult<any>) => any,
 ): Subscription {
diff --git a/packages/apollo-client/src/util/wrap.ts b/packages/apollo-client/src/util/wrap.ts
index bfe752308d7..a50387071c9 100644
--- a/packages/apollo-client/src/util/wrap.ts
+++ b/packages/apollo-client/src/util/wrap.ts
@@ -1,6 +1,6 @@
 // I'm not sure why mocha doesn't provide something like this, you can't
 // always use promises
-export default (done: (...args) => void, cb: (...args: any[]) => any) => (
+export default (done: jest.DoneCallback, cb: (...args: any[]) => any) => (
   ...args: any[]
 ) => {
   try {
diff --git a/packages/apollo-client/tsconfig.json b/packages/apollo-client/tsconfig.json
index 1b00f4438f4..42d347c8f0a 100644
--- a/packages/apollo-client/tsconfig.json
+++ b/packages/apollo-client/tsconfig.json
@@ -10,9 +10,13 @@
     "strictNullChecks": true,
     "noUnusedParameters": true
   },
+  "include": ["src/**/*.ts"],
+  "exclude": [
+    "**/__tests__/**/*",
+    "**/__mocks__/**/*"
+  ],
   "files": [
     "node_modules/typescript/lib/lib.es2015.d.ts",
-    "node_modules/typescript/lib/lib.dom.d.ts",
-    "src/index.ts"
+    "node_modules/typescript/lib/lib.dom.d.ts"
   ]
 }
diff --git a/packages/apollo-utilities/src/getFromAST.ts b/packages/apollo-utilities/src/getFromAST.ts
index 1db77ac1fbf..3db665b514e 100644
--- a/packages/apollo-utilities/src/getFromAST.ts
+++ b/packages/apollo-utilities/src/getFromAST.ts
@@ -192,16 +192,18 @@ export function getDefaultValues(
   ) {
     const defaultValues = definition.variableDefinitions
       .filter(({ defaultValue }) => defaultValue)
-      .map(({ variable, defaultValue }): { [key: string]: JsonValue } => {
-        const defaultValueObj: { [key: string]: JsonValue } = {};
-        valueToObjectRepresentation(
-          defaultValueObj,
-          variable.name,
-          defaultValue as ValueNode,
-        );
-
-        return defaultValueObj;
-      });
+      .map(
+        ({ variable, defaultValue }): { [key: string]: JsonValue } => {
+          const defaultValueObj: { [key: string]: JsonValue } = {};
+          valueToObjectRepresentation(
+            defaultValueObj,
+            variable.name,
+            defaultValue as ValueNode,
+          );
+
+          return defaultValueObj;
+        },
+      );
 
     return assign({}, ...defaultValues);
   }
diff --git a/packages/graphql-anywhere/src/graphql-async.ts b/packages/graphql-anywhere/src/graphql-async.ts
index f20b494ef48..f9051b33e4b 100644
--- a/packages/graphql-anywhere/src/graphql-async.ts
+++ b/packages/graphql-anywhere/src/graphql-async.ts
@@ -42,7 +42,6 @@ import {
  * but below is an exported alternative that is async.
  * In the 5.0 version, this will be the only export again
  * and it will be async
- * 
  */
 export function graphql(
   resolver: Resolver,
diff --git a/packages/graphql-anywhere/src/graphql.ts b/packages/graphql-anywhere/src/graphql.ts
index 352b31b3614..da535d5ea72 100644
--- a/packages/graphql-anywhere/src/graphql.ts
+++ b/packages/graphql-anywhere/src/graphql.ts
@@ -75,7 +75,6 @@ export type ExecOptions = {
  * but below is an exported alternative that is async.
  * In the 5.0 version, this will be the only export again
  * and it will be async
- * 
  */
 export function graphql(
   resolver: Resolver,