Hello everybody and thanks
for joining my session today. As the slide says,
my name is Tod Golding and I'm a partner solutions
architect at AWS, and I am part of a team
that is called SaaS factor, and that team basically helps
different organizations that are in various stages
of building or operating or delivering a SaaS solution on AWS.
And as you can imagine, one of the really common themes
we run into with SaaS organizations is that these organizations
often are starting out in this sort of classic
monolithic model where they've built sort of
maybe a legacy solution or they built
a newer solution and it is running
in a monolithic pattern… it may be deployed on-premises,
it may be deployed in the cloud, but the key theme here
is that each of the customers are often running
their own environments. They may be running
with their own customizations, they may be running
separate versions, and what these organizations
find is that, essentially, it gets very difficult to scale and operate
a business in this matter and they can't grow
as fast as they want, the operational burden
is getting higher, they can't innovate
as fast as they want, and this is what really,
sort of, motivates them to want to move
to a SaaS delivery model. They see the efficiency of SaaS,
they see the innovation pace of SaaS, they see the cost
in operational efficiency at SaaS. And they are really
sort of interested in saying, how can I take
this monolithic solution that I have
and migrate it to a SaaS model. And specifically lots of them
are very compelled to move into what we call
a serverless SaaS model, and that is a model
that leverages AWS lambda as its sort of
compute basis here and so we are going to
in this session, is we are going to look
at this exact journey, we are going to look at what it takes to move one of these
monolithic solutions from one of these classic
sort of models, incrementally into a SaaS model that is
based on serverless technologies. And the goal here
is to figure out how can you sort of
make this transition in a way that still addresses
the needs of your business but also moves you toward this fully
modernized, multi-tenant experience. Now in this session we are
looking at a 300 level session so we are not going to be
digging into the weeds and looking at code
and some of those bits, we certainly have
those bits out there and I encourage you
to go find them and look up the AWS Factory and other
bits and you'll find that depth. But today we are going
to be looking more at what's the architecture
behind this model. We will definitely
get into the tech of this, but we are not going to be sort of opening the IDE
or looking at code. So hopefully that sort of fits
with what your expectations are. Now, before we sort of
get into the tech of this, it is important to sort of talk
about where we are starting and where we are trying to get to, because the starting point
for every business and their goals
are often very different. But generally everybody would love
to have the option to say, can we just go away,
re-write our entire solution, deliver it in a SaaS model, and we will already
be fully modernized. But that isn't reality,
and that isn't a luxury that most organizations really have. Most organizations
are also struggling with business pressures they have. They need to get a SaaS product
to market fast, they have competitive pressures
that are out there, they have market pressures, and so they are always in this sort
of in this nature tension between re-write, re-build, and get to market as fast
as they can. Well in reality when you set off
on this migration path, we encourage people to try to get to
market as quick as they possibly can. If you can at least get
a SaaS product into market and you can start to get
feedback from your customers, then your new version
of your product, as you can sort of have
all of those best practices and still have all of this feedback
from your customers incorporated into that experience. Now what makes this
particularly challenging is that the starting point for this
from a technology perspective isn't particularly easy, right, if you look at a classic sort
of monolithic architecture, what you'll see here is we have this
sort of classic end-tier experience, we have a web tier and some sort of
app tier where our business logic is, and some sort of storage tier
maybe where our database lives, and what we find is these things
tend to be super coarse grained, and they tend to have
a really high coupling. So if you dig, for example, into the
application tier of your environment, you might have
individual services, you might have some frameworks
and libraries, but what you will
ultimately find here is that these services
are really tightly connected and that they are really hard
to sort of pull out and deploy on their own. What we will also see is that
when you look at the databases, the database will tend to have
really tight coupling to all of these services, so each service author essentially
has the ability to go and touch any part of the database they want
and we'll even see business logic pulled out of this application tier
and moved into this storage tier. And so this just creates all these
sort of connections that are hard, and on top of all of this, this tends
to get deployed as a single unit. So we'll see the one big unit
of deployment that sends out the web
and the app tiers, and so this becomes
your single unit of scale, your single unit of fault tolerance, all those things that are sort of
classically struggling - make monolithic
environments struggle. And so, this is our starting
point of migrating and we have to figure out
how can we get from here to a serverless, modernized model. So the good news here is that we have
a really natural sort of starting point
for our modernization exercise, which is one that allows us
to sort of minimize the amount of work
we have to put into just getting our SaaS solution
available to the market. So what you see here in this slide
is an example of what we would call
a siloed SaaS environment. And in this solution
basically what we are doing is we are taking that monolith and we are deploying it
into a shared SaaS environment, so we are essentially going to deploy
a separate stack for each tenant, but we are going to deploy it into this universally sort
of managed SaaS environment. So, the key thing here is that
each one of these environments, each stack that is deployed
for each tenant, is the exact same stack
with the exact same infrastructure, and they are all running
the exact same applications, and that's key here and this gets us
away from some of the challenges of having individual customers
running their own versions, or having all of this sort
of one-off customization, and this sort of fundamental
to making your SaaS product available to the market. So we are going to take that monolith
and we are going to make it available inside the shared environment
and then we are going to surround it with all of these SaaS constructs
that allow us to run and allow us to operate
our business in a SaaS model. So you see for example at the top
we introduce onboarding and identity, and we will dig
into those in more detail, but essentially this gives us
a way for a tenant or for our own processes
to come in and provision a new tenant into this experience
in a very frictionless manner, and be able to associate users
with individual tenants and flow that tenant context
into the stacks of our offering. Now on the left hand side
you will also see sort of some of the operation
bits we have to bring along with us to make this
a fully SaaS environment, so we will need new Dev-ops
and new deployment sort of mechanisms to deploy the SaaS environments, and we will need new management
and operations tooling, that will allow us
to collectively manage all of these tenants
through a single pane of glass so we can see the health
of individual tenants, or the collective health
of the overall system all through a single,
unified experience. But then also on
the right hand side you'll also see
some of the other bits we will have to introduce
to make this a SaaS environment. We are going to need
to have some notion of sort of metering
and billing here that will let us capture the activity
of tenants in our environment so we can generate
a bill for them. And you will also see
metrics and analytics. Here is where we are going
to introduce an instrument, your monolithic environment,
with new metrics and analytics, that give us visibility
in how tenants are consuming our environment.
But the best news of all of this is, it lets you essentially move
your monolithic environment in, present it to your customers as SaaS,
and buys you the time to now say, okay, how can I now begin to morph
this into a modern application. Now the first step
in that process, to me, and the step that I will
sort of drive home here and I'll drive home
at the end of this is, you should start this entire process
by introducing tenancy into your environment.
Some organizations will go away and build their multi-tenant
application but build it with one customer,
one tenant in that environment, and that really doesn't exercise
a lot of the multi-tenant pieces that we need to put into
the belly here. So from day one I would
really like for you to see you putting in
all these multi-tenant constructs and exercising your system,
testing your system, operating your system,
in a multi-tenant fashion. So the first step
in that process, obviously, is to introduce
this onboarding process, and what we really want, again, is this frictionless
onboarding process, so this is either somebody
coming to a sign-up page, or some tool you have inside,
launching this onboarding process, and then having that orchestrate
all the other bits that are needed to get your tenant
introduced into your environment. So, we will need to create,
for example, a tenant in our tenant
management system, and that will store the tenant,
their bill, their plan,
any kind of configuration, and that will give us back
some kind of tenant identifier, and then we will need to go
create the user for that tenant, so we will have to take
the user that gave us, the email is often the user
in this scenario, and we will go out into
incognito in this use-case and will create that user
inside of incognito. Now there's lots more moving parts
to what happens in incognito and there's other talks on that, but essentially here we are
going to create a binding between the user and the tenant using
custom claims inside of incognito and I encourage you to go look
at that in more detail because that is
pretty fundamental to this. The other bit we are going to
create here are IM policies. So we are going to go out
and create any policies that are needed to enforce
the isolation between this tenant
and other tenants. Again, another topic
that has a lot of depth behind it that I encourage you to go look at.
Finally, you are going to go out now and say well now
we've got the tenant, we've got the user created,
now we've got to go out and create a relationship
to the billings system. Often you either have
a third party billing system or you have some
internal billings system, but as part of having
a new tenant come on board, we have to create that tenant
inside that billings system so that they are set up
with whatever plan they have or whatever billing constructs they need to generate
a bill for them. And then the last piece,
which is sometimes optional, but is required
in this particular use-case, is the provisioning of
your actual tenant environment. So here, because we are
running in a siloed model, each one of our-each
one of our tenants has to have infrastructure provision
for them as part of coming onboard, and we will look at that
in more detail. But, fundamentally, when you have
all of these pieces in place, you now have the bits you need
to identify a tenant, identify their isolation policies, know what their relationship
is to billing, and you have all of
their infrastructure created, all by one automated process.
Now, I said we would talk about the-what that automation
and provision looks like, let's dig into that
a little bit more. So if you look at what we are
doing here as our starting point, because again we are starting
with the silos, you'll see that we'll come in,
we'll come in through route 53, you'll see we have a subdomain here
which is tenant one, that identifies our tenant here, and that tenant will be routed
to the infrastructure that is supporting our silo,
in this case I've shown a VPC, multi-AZ,
classic sort of AWS constructs, along with some compute
and some storage. Naturally what's in this
will depend on what's in your monolith
to get it running, but generally look at a VPC
per tenant kind of model as a really common approach
that we will see people use here. Now that's a tenant
that is already running, but we now want to onboard
a new tenant, so we will come in
through our onboarding process, we will register this new tenant, and like the last step
in the previous slide, we will now provision all of the infrastructure
needed for this tenant, in this case another VPC, AZs,
all the things that are needed here, we will provision that
into the common environment, and then the last step in this will
be to actually set up the routing, so tenant two, now when they come in,
they automatically route. And the nice part of this is,
once all of this is automated, adding ten more tenants,
adding one hundred more tenants, it won't really matter,
you've got sort of all the friction removed from this experience
and you can sort of ask the business, go ahead, bring me as many tenants
as you'd like, obviously you have to think
about limits and scale and other sorts of things
in that equation, but in general, you are ready to sort
of grow the business in a SaaS model. Now, the next piece of this is,
now that we have these tenants here, is that we have to think about how we are going to get
tenant context for these tenants and flow that through
our architecture. This really happens during
the authentication process, so here I'll authenticate a user,
and then as part of authenticating I'll go out to that
incognito identity provider and get the data
that I created essentially when I provisioned this tenant and so that will return
to me a JSON webtoken, a jwt, and that jwt will have in it
not just my user identity but also all of these
other attributes that represent me
as a tenant and so the user identity
plus the tenant identity often gets what we'll call
a SaaS identity, and that gives us
this first class object that we can then flow
through our architecture and give us access to these tenant
attributes any time we need them. So here you'll see I flow the jwt
into my siloed SaaS environment and you could say here,
well do you really need the jwt here… well not-maybe you don't
need it so much yet because your siloed and each silo sort of already knows
which tenants its associated with, but there are even use-cases here
where that jwts needed for you, which is, if you look for example
at logging, as we log now, we are not just going to log, we are going to log
with tenant context, so we need this jwt to say
which tenant I am logging on behalf of and record
that information to the log, or if we record metrics
or metering or billing, all that needs tenant context. So even while we are
still in this monolith, we can use this jwt
to access that context. Okay, so now we've sort of
got tenancy established, we are running in a siloed
SaaS model, we have all this first class
sort of constructs in place, the hard question is now, okay, how do we start to cut over
to a modernized architecture. How do we get to that serverless
SaaS architecture, and the starting point for this is pretty obvious
and straight forward, right. We are still going
to have our monolith, so when we come in,
we will have two tenants come in, and they'll hit our routing,
but when they hit the routing they will still go
to the individual monoliths, and at this point, that all
still remains exactly as it was. We'll also see we have
these sort of shared services we talked about running
on the side over here, tenant management,
user management, and so on. But now we at this point
we get to stop and ask ourselves, how can I start to create the first serverless microservices
for my application, and what we are going to do now
is look at our app and try to identify some really
good candidate microservices that can be the first microservices
that come out of our system. And we will talk
a little more about it, how you might identify those. But right now the key here
is that we've identified some piece of functionality that makes a good target
to carve out first, we'll carve it out,
we'll have our first microservice, and now you'll see here, my web tier
comes-when I come into my web tier it may be hitting
the old monolith app tier or it may be hitting
my new microservice, and this microservice is now
a multi-tenant microservice and now it is shared
by both of these tenants, we are not going to have
the silos anymore, we are slowly moving to a
multi-tenanted serverless construct. The hardest part of this, though, is not just identifying
this microservice, as part of moving this code
out to this microservice, you also have to bring
the data with you. And this is where
it can get really sticky because if you have
these big monolithic databases, how do I find a domain of data
that I can carve out that isn't somehow dependent on by fifteen other services
that are inside my monolith, and this is just
sort of the challenge of getting these first services
up and running. But when you bring it out, you really want it to be
a first class microservice that has-that is
incapsulating the data and providing you
a true microservice experience. Now – an alternative
sort of path for this and one that I-we sort of encourage people
take here is to also start thinking about how to break that web tier
out of the monolith as well, and the first step in that process
is often to say, let's take that out of
individual stacks of our tenants, and let's have a shared,
multi-tenant web tier that can scale on its own
but it's truly multi-tenant, so we get the economies
that scale what we want here, this can scale in and out,
it is a little easier to manage, costs us a little less,
but we mostly leave it intact, we just break it out
as a shared multi-tenant construct, and then we go through
a routing construct to get to the app tier
and the microservices that we have, but now we have at least
created some boundary between our app tier
and our web tier and they are clearly sort of
separated from one another. Now the best evolution of this,
if you have the opportunity to do it, is to pull that web tier out
and truly move it to sort of a modern
application experience. So here, if you look you will see
we have our microservices and our sort of our monolith
and our microservices and our shared services, and now what we will do
is we will take that web tier, and we will actually move it out
to a single page application and run it in React or Angular
or one of those modern tools and we will use API gateway
to connect to our services. So here you'll see,
got my application running and hosted on S3 here,
I am coming through the API gateway, and then the API gateway is hitting the individual services
of my application. And the really cool part of this is,
is that once I get to this stage, now it is really just my job
to figure out how can I slowly move the rest of
the functionality of my application over to these microservices, and what will see is that monolith
slowly sort of fade away, and the more and more microservices
that you move over, the more momentum you create, and the faster this evolution
starts to happen, but when you are all done,
the good news is, you've just-you got
a fully modernized architecture – your serverless microservices, your modern web app
going through the API gateway, and you've got all these surrounding
bits of SaaS there ready for you. Now one of the things I really
encourage people to do is to not cut corners when they build
these first services, right. When you build
this first microservices, you're laying the foundation
for all of the other microservices that are going to come
in your system. And what we tell people when
you are building a microservice, invest heavily in hiding away the details of tenancy
from your developers, so for me it is ideal
if a developer feels like they are just writing a single tenant
sort of application, something that has no awareness
of multi-tenancy whatsoever, and that all of sort
of the nuts and bolts of how multi-tenancy work
are entirely outside of their view. So in this example
you'll see how I put logging and metrics
and analytics and data partitioning and data access sort of
in these libraries that are on the outer edge
and my code and my function just essentially says
hey I want to log something or I want to record a metric,
or I want to get to data, they don't worry about
what the tenant context is, they just take the jwt token
and pass it through that experience and let that get resolved
outside of their view. Even with tenant isolation
we will do the same thing here, right, we will try to enforce
tenant isolation in a way that is outside
of the developers. But the key take-away here, no matter
how you surround the libraries, is that you don't want to policies
of your multi-tenancy and details of your tenancy
all through the function-all through the functions
of your serverless application. You want to push that out
to common constructs. Now one way to do this that is
really powerful inside of lambda is by using this notion
which is called lambda layers, and a lambda layer
basically lets us say, hey we are going to create
this shared, separately-deployable construct
that has all this shared code in it, and we are going to be able
to deploy it in a way that is used
and referenced universally by all the functions
of our applications. So, if you look
at the right hand side here you'll see logging
and metrics and these things we've been
talking about deployed, and they are deployed as a layer, and then I have the functions of
my application on the left hand side and these individual functions
all just reference that layer, so if tomorrow I decide
I have a different way I want to handle token management or logging
or something of that nature, I can update those policies
inside the layer, deploy a new version
of the layer, and then have these
different functions just get access
to that new layer without having to-to sort of
redeploy their services or at least not make
a big invasive change that somehow spans
all of these services. So this is super powerful
construct and something
within the serverless side we encourage very strongly. Just to get a sense
of what that might look like, we have a metric example here. So I have a function
that is in my microservice, that microservice
wants to record a metric, but I don't want the developer
to know much about it, so they just say record metric, pass the token
and the metric through. Some metric services
in the layer here, that is going to say,
go get me the tenant ID, using the token,
that will crack the token open, get the data out about the tenant,
return to the tenant, and then it will actually publish
the metric with the tenant context. And all of this code here,
the metrics, the token management, all of that,
is running inside of a layer. Now the thing you have to factor
into all of this is, well all of our new microservices
get all this goodness because we are building it
into these microservices as they come and you still have
this monolithic code that's out there that needs
to participate in this overall SaaS experience. So while we'd love to say
you're not going to touch that code and we can leave it
entirely alone, the reality is,
to introduce tenant context and apply tenant context fully across
your whole operational experience, you may have to go back
and retrofit in some concepts into the monolithic code here. So, if I want tenant aware
logging, for example, I'm going to want to introduce
some kind of framework and inter-change my logging
here in my monolith so it sends this log message,
it pulls out the tenant context, and it sends that
tenant context through. Same with metrics
and billings and so on. So we're going to have to modify
some of that monolithic code to get all of these
other bits to work, and I think that
that is worth it because you certainly don't want
to have a situation where, oh here is all the goodness
coming out of my new microservices, and then I have this sort
of separate puzzle to put together for the monolithic
operational view of this. So I mentioned earlier
that we'd try to like, talk about-what are the best ways
to find the services that are the good starting points,
and there is no magic bullet here, and a lot will depend on your domain
and what your monolith looks like, but there are some patterns
that I've seen. Certainly-if one of the ways
I've seen people approach this is to just go after things that
have minimum impact on the business. Can I find a service that if it were
to have fault tolerance, if it were to have the ability
to withstand issues, so if it had outage
it wouldn't impact or cascade through the entire system, that may be a really good
starting point because then you have
the freedom to sort of do what you want with that service
without-without worrying about the overall
continuity of the business. One of the more obvious ones is, is just finding the services
that are not tightly coupled, like if you can find those, they are often hard
to find in a monolith, but if you can find those,
that is often a sweet spot and a really good place
to get started. And then, this one is-sorta feels
like in opposition to the others, but it is a possibility
which some people will say there is this really huge pain point
in our existing application, it is a huge nightmare for us, it is already imposing
all of this operation burden, can we use that as the target
for our best service and yes, that adds risk, but we also start
to address real pain points in our existing environment. And the last one is
really-really more about these data. Can you find data domains, can you
find areas where the data decouples – I wouldn't want this
to be a data driven exercise, you should find your microservices
based on the right set of criteria, but sometimes the data
can help steer you toward that. So what are some of the key
takeaways here. Well hopefully you can see
that this silo SaaS model that we start with, that really buys us
a lot of time, right. If we can get into that environment,
surround that with all that SaaS goodness that we talked about,
now I can present to the market a SaaS offering,
take some of that pressure off, and really allow myself to think
about how to be deliberate
about my grading incrementally the rest of that
application to this serverless SaaS model. I also hope, and I know
I drove this home pretty hard and I'm sort of going to emphasize
it again, which is start out
with these tenancy concepts being introduced in your environment
from the very beginning. Think about what it'll need
to operate it, think about how you'll do logging, think about how you'll do onboarding,
do all of that early, cause now when you have that surrounding
your architecture, it will force sort of
multi-tenant questions inside the implementation
of your services. The other thing is, you'll know that your monolith
will have to change some, right. There's a hope that you
can minimize that impact, but I also want to be realistic – some bits of your monolith
are going to change here. We just want to try
to sort of balance how much we change that versus what it will mean to migrate that
to a new serverless microservice. And then the data piece of this,
there is just no getting past it. It is a hard part of this puzzle,
especially at the very beginning, and I think as you get further down
the line, it gets a little easier, but-but expect that you are going
to spend a little while figuring out how to tease things
out of your data model. And then really I couldn't emphasize
this more, expect that you are kind of going
to get the first few services wrong, right, like you may end up picking
some services and then iterating on,
decomposing them further, and so on, and this sort of ties
into my next point, which is just expect them to evolve. Like don't think of them
as a one-time decision, expect the overall service
landscape to evolve. And finally, when you build
these new microservices, set the serverless bar for them high, set the multi-tenancy bar
for them high, build really good
foundational services from the start, and then use those foundations
services to sort of see the momentum toward the next set of microservices
that you are going to build. Now I did want to highlight
really quickly that there are some additional sessions
that are going on over there – I'll just let you look at the screen
- but we are looking at EKS, and some new offerings that are
coming from the SaaS Factory team, there is also content available
on the AWS SaaS Factory page
around lots of these topics so I encourage you to look there. But I hope this was a really
helpful session for you, I hope you got a lot out of it, really looking forward to seeing
more and more people succeeding in migrating their solutions
to a serverless SaaS model, and hope you enjoy
the rest of the conference.