Deep Dive Into Serverless

February 7, 2023
Ryan Jones
5 minutes to read

Cloudfront can be simply defined as a CDN (Content Delivery Network), caching your static assets in a datacenter nearer to your viewers. But Cloudfront is a lot more complex and versatile than this simple definition.
Cloudfront is a “pull” CDN, which means that you don’t push your content to the CDN. The content is pulled into the CDN Edge from the origin at the first request of any piece of content.

In addition to the traditional pull and cache usage, Cloudfront can also be used as:

  • A Networking Router
  • A Firewall
  • A Web Server
  • An Application Server

Why is using a CDN relevant?

The main reason is to improve the speed of delivery of static content. By caching the content on the CDN edge, you not only reduce the download time from a few seconds to a few milliseconds, but you also reduce the load and amount of requests on your backend (Network, IO, CPU, Memory, …).

Static content can be defined as content not changing between two identical requests done in the same time frame.

Identical can be as simple as the same URI, or as fine grained as down to the authentication header. The time frame can range between 1 second to 1 year.
The most common case is caching resources like Javascript or CSS and serving the same file to all users forever. But caching a JSON response tailored to a user (Authentication header) for a few seconds reduces the backend calls when the user has the well-known “frenetic browser reload syndrome”.

Edges, Mid-Tier Caches, and Origins

Cloudfront isn’t “just” some servers in datacenters around the world. The service is a layered network of Edge Locations and Regional Edge Caches (or Mid-Tier Caches).

Edge Locations are distributed around the globe with more than 400 points of presence in over 90 cities across 48 countries. Each Edge Location is connected to one of the 13 Regional Edge Caches.

Regional Edge Caches are transparent to you and your visitors, you can’t configure them or access them directly. Your visitors will interact with the nearest Edge Location, which will connect to the attached Regional Edge Cache and finally to your origin. Therefore, in this article, we will refer to Cloudfront as the combination of Edge Locations and Region Edge Caches.

What Have We Learned?

Cloudfront is more than just a simple “pull-cache-serve” service

  • You improve delivery speed to your visitors
  • You can increase resilience by always using a healthy backend
  • You improve overall speed to your backend by leveraging AWS’s backbone
  • You can modify any request to tailor the response to your visitor’s device or region
  • You don’t always need a backend
  • You protect your backend by reducing the number of calls reaching it

Access free book

More from Serverless Guru

Building Serverless REST APIs for a Meal Prep Service with CloudGTO

October 31, 2023
Learn More

How to build an AWS AppSync GraphQL API with multiple data sources

October 26, 2023
Learn More

Building a Secure Serverless API with Lambda Function URL and CloudFront — Part 1

October 17, 2023
Learn More

Invoking a Step Functions Workflow from Mobile Application Built with Amplify & Flutter

Let's Talk

In the first part of this series, we built a step functions workflow for a simple apartment booking scenario using the AWS Step functions low code visual editor.

In the second part of this series, we built the same workflow using CDK as IaC, Appsync and python, while invoking the step functions execution from a Lambda function.

In the third part of this series, we built the same workflow using SAM as IaC, Appsync and python, while invoking the step functions execution from a Lambda function.

In this post, we’ll be invoking the step functions workflow we created above from a mobile app built with amplify and flutter.


Solutions Architecture


In-order to properly follow through successfully with this tutorial, you’ll need to have checked through these prerequisites:

  1. Installed and Running Amplify CLI
  2. Installed and Running Flutter Framework
  3. Successfully completed and deployed any of the applications in PART 2 Or Part 3
  4. Installed Android Studio or Vscode


This isn’t a flutter tutorial, but rather a tutorial on invoking step functions from a flutter application. So I’ll assume you already know how to use Flutter. If you don’t, don’t worry. You can always start here

Setup FullStack Project

Create a new flutter application
flutter create amplified_todo

Add Amplify to your application

Go to and search for amplify flutter and copy this package and version:

In your root directory, search for 'pubspec.yaml' file and add the amplify package to it.

amplify_flutter: ^0.6.6

Since we’ll be accessing the GraphQl API we created in PART 3 or PART 4 of this series, we also need to install the Amplify API library.

amplify_api: ^0.6.6

Therefore, my 'pubspec.yaml' dev_dependencies now has this structure:

dev_dependencies:  flutter_test:    sdk: flutter  # The "flutter_lints" package below contains a set of recommended lints to  # encourage good coding practices. The lint set provided by the package is  # activated in the `analysis_options.yaml` file located at the root of your  # package. See that file for information about deactivating specific lint  # rules and activating additional ones.  flutter_lints: ^2.0.0  amplify_flutter: ^0.6.0  amplify_api: ^0.6.0

Install the dependencies by running the following command. Depending on your development environment, you may perform this step via your IDE (or it may even be performed for you automatically).

flutter pub get

Update Target Android SDK Version

From your project root, navigate to the 'android/app/' directory and modify build.gradle using a text editor of your choice and update the target Android SDK version to 21 or higher:

minSdkVersion 21

If you are using Flutter 2.10 or above, you must ensure that your app supports an up-to-date Kotlin version. This will typically be version 1.5.31 or higher.

You can do this by updating the Kotlin version in your app’s android/build.gradle file:

buildscript {
    ext.kotlin_version = '1.5.31'

Initialize Amplify

From the root of your application, run the command 'amplify init'

Give your project a name. When you installed and configured Amplify CLI, you created a profile. Please choose that profile when the CLI prompts you to choose an authentication method.

You should see a similar screen to the one below once you are done.

Amplify creates a file called 'amplifyconfiguration.dart' in the 'libs' folder.

We have to populate this config file with our backend configuration.

Get Amplify Config From AppSync

Open up AppSync on the AWS console and navigate to your project.

Download the configuration by clicking on the orange 'Download Config' button.

Now open up 'amplifyconfiguration.dart' and fill in the details like so:

const amplifyconfig = ''' {
    "UserAgent": "aws-amplify-cli/2.0",
    "Version": "1.0",
    "api": {
        "plugins": {
            "awsAPIPlugin": {
                "cdkMomoApi": {
                    "endpointType": "GraphQL",
                    "endpoint": "",
                    "region": "us-east-2",
                    "authorizationType": "API_KEY",


Change the AppSync name from 'cdkMomoApi' to yours, alongside the rest of the details.

Updating main.dart

Open your 'main.dart' file and initialize Amplify and Amplify API.

import 'package:apartment_complex/welcome_screen.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
// Amplify Flutter Packages
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:amplify_api/amplify_api.dart';

// Generated in previous step
import 'amplifyconfiguration.dart';
void main() {
  runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  State createState() => _MyAppState();

class _MyAppState extends State {

  Future _configureAmplify() async {

    // Add any Amplify plugins you want to use
    final authPlugin =  AmplifyAPI();
    await Amplify.addPlugin(authPlugin);

    try {
      await Amplify.configure(amplifyconfig);
    } on AmplifyAlreadyConfiguredException {
      if (kDebugMode) {
        print("Tried to reconfigure Amplify; this can occur when your app restarts on Android.");
  void initState() {
    // TODO: implement initState
  // This widget is the root of your application.
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Apartments',
      theme: ThemeData(

      home: const WelcomeScreen(),

GraphQL Mutation

Remember our GraphQL mutation expects an ID, and the Step Functions ARN. Here’s how to create a GraphQL mutation in Flutter with Amplify.

Future startStepFunctions(String id, String arn) async {
      String graphqlDoc =
          mutation add(\$id:ID!
                        \$arn:String!) {
  addStepFunction(input: {id: \$id, arn: \$arn}) {


      var operation = Amplify.API.mutate(
          request: GraphQLRequest(
            document: graphqlDoc,
            apiName: "cdkMomoApi",
            variables: {

          var response = await operation.response;

          var data =;

      if (kDebugMode) {
        print('Mutation result is$data');
        print('Mutation error: ${response.errors}');

      if (kDebugMode) {

Please grab the complete code and try it out.


In this series, we looked at how to create and invoke a step functions workflow through:

  • The AWS Console
  • Using CDK for Infrastructure as Code
  • Using SAM for Infrastructure as Code
  • Using Amplify and flutter

Hope you enjoyed it. I’ll love to know your thoughts on this series and Step functions as a whole. Cheers!!

More from Serverless Guru

Join the Community

Gather, share, and learn about AWS and serverless with enthusiasts worldwide in our open and free community.