Any recommendations or hard-won tips for how to na...
# general
c
Any recommendations or hard-won tips for how to name services? I’ve noticed patterns like - • {thing}-{type} : “notes-api”, “notify-job”, etc. • {type}-{thing} : “api-notes”, “job-email”, etc (has benefit of grouping types alphabetically) • {resource}-{type} : “cognito-trigger”, “bus-trigger” Also curious what handful of types folks tend to group services by - • ‘api’ – crud actions • ‘job’ – generic for any other multi-step operation? • ‘trigger’ – service that initiates another resource or external service? • others?
a
Subscribe.
Yeah been discussing about this with my CTO for some time.
I can’t get it right.
For functions, I don’t like to name it “function”… I name them..
{env}-{company}-{stack}-{func}
.
Like, for me…
dev-yabble-tasks-getById
.
The stack in that case is named
tasks-stack
, but I strip the
-stack
from the name.
c
Thanks Adrián. So in this example, your service is in effect named
tasks
?
a
What is service for you?
🙂
There is no “service” concept in SST/CF/CDK.
But yes, I have a folder which is called
tasks
and it has functions like
getById
,
create
,
updateById
.
Service -> just a folder, nothing else.
c
Thinking ‘service’ in terms of architecture = a discrete, autonomous service in application that can receive, process, send events.
May have 1 service that serves as backend-for-frontend of a specific part of the app, another that is responsible for communication with a 3rd party service, etc
a
Yes, I get it, I use the same concept.
That’s why a service it’s just an architectural abstraction, just that.
Nothing logically.
But yes, I group them “by service”.
And also I never name a service like “tasks Api”.
c
Exactly
a
Because my service could have more than APIs… maybe a job… or whatever.
The
service
it’s just a group of functions.
Then the API it’s on CDK -> and utilizes functions defined in the service.
c
For names, wondering what might be good strategies to name these to align with purpose that would help create an intuitive taxonomy across app - name would be reflected in service directory names and their corresponding stack names
Ah, that’s interesting
Because my service could have more than APIs… maybe a job… or whatever.
So in that case prepending/appending service name with a type could be too limiting or force unnecessary breaking up a service
a
Yes.
c
Part of this is thinking that would largely have 1:1 between services and corresponding stacks
to help isolate development/deployment across services
a
Exactly.
I do that.
1 service, 1 stack.
But also my stack, can have the EBridge, some SQS.
So that’s why the concept of ‘service’ only applies to the “group of lambdas”… just that.
All the other stuff it’s architecture components, EB, SQS, SNS, etc.
But are all owned by the same Stack.
This is a concrete example that I have: TasksStack: • Tasks API (api gw v2) -> points to functions inside folder ->
backend/services/tasks
• Tasks Event Bridge (used to communicate when tasks are created) • etc
c
So you’re not creating a new stack for each service plus a couple of common stacks? And instead on one stack that provides resources for most services?
a
I have some “common stacks” yes.
Like the WAF, or VPC, VPN.
c
I hit enter at same time; trying to grock one you posted before that
a
Might delete this screenshot later 😂
Also, my index doesn’t have reference to stacks, due I have too many, just reference a class (Network.ts)
c
thanks Adrián - processing that; I think it’s making more sense
a
Yeah been playing with this for some time, I have more than 20 stacks at the moment, still trying to improve it.
This is my Index file,… just references CLASSES, which contains several stacks on each of them.
It’s incredible how easy is to re-use or share code and resources.
I’m never going back to CF or SLS in my life.
c
are you grouping your stack definition and functions in the same service directory?
a
No.
I have Infra folder, and Backend folder.
Not sure if that’s what you mean.
c
ah, ok, gotcha
a
3 main root folders.
Maybe going to move
packages
away from Backend and create a shared-packages folder for everything.
Due I might have infra packages, backend packagres, frontend packages.
c
this is super helpful
a
😄
It’s a bunch of ideas and talking with different guys here in this slack.
c
so in
infrastructure/src
dir’s like
networking
and
onboarding
are stacks that correlate to services, right?
a
I would say.. onboarding it’s a feature.
I would say those folders doesn’t follow a convention.
networking
-> it has VPC, VPN, etc
onboarding
-> a feature of the platform (where the users onboard to the website).
So it’s not actually feature based, I don’t love it.
marketing
-> not a feature, just some stuff related to Marketing websites, haha.
Definitely a mix of things…. not a service for sure.
c
that makes sense, so fair to say your stacks = service | feature set | common area of functionality?
a
Yes, exactly.
I did it in that way for some reasons.
For example, I have X amount of environments, like.. PR1, PR2… dev, stage, prod…
And NETWORK only has to be created for `dev`… not for PR1, RP2, etc.
c
love how you have the stack groups, when needed, and barrel file to organize / access them later
a
Grouping all networking stuff into a single stack of more than one, it’s easier to handle.
Yeah.
Also I designed this i a way that I can share dependencies easily, and make it clear what depends on each thing.
If you check my index, it’s pretty clear what is dependent on what.
c
this is great advice, thanks again Adrián - let’s see how bad I can screw it up in implementation 😂
a
Hahaha, yeah, this can be always improved, has been growing for months, but well… still learning from other guys here.
c
@Adrián Mouly re-reading this a bit and a couple follow-up questions if and when you have time – 1. Could you possibly share an example of how you’re wrapping up related stacks into an index ‘class’ stack (e.g.
Network.ts
)? I’m trying understand how the underlying stacks (e.g.
NetworkVpcStack
) are created when you call only
new Netwwork(app)
in infra/src/index 2. Other than setup efforts, have you run into any unexpected concerns or costs with this level of separation and its likely duplication of resource types across stacks? 3. Bonus event-related question - are you setting up EventBridge as the event hub within services – or relying on SQS/SNS for intra-service event communication and using EventBridge in a separate stack as way to communicate between services?
s
wow, long thread! for what it’s worth, this is how I name my stacks
and then functions are
(stack name)-(function name in camelCase)
.. so everything is grouped alphabetically
a
microservices
aggghhh, can’t live with that long name.
😄
@Clayton going to send examples in a minute, finishing some grooming.
s
haha. we have
v2-frontend
and
v2-microservices
for our two repos
a
@Clayton this is for point 1;
About 2)… I don’t see why costs will change, due all I’m using it’s serverless… and also, I’m not duplicating anything… instead I’m reusing as much as possibly sharing those references by parameter.
About 3).. My arch it’s totally event-driven, and I have several event-buses (mostly created by-feature)… and then sharing that Bus as a dependency between stacks … for example maybe one stack has a function that Publishes an event, and other stack has a function that is Triggered by the event… so I need to share that resource… the stack that Publishes is the one that creates the Bus… then there is a stack dependency there. I’m also using SQS but that is used only on the stack, not shared with other stacks. To resume… I share EventBuses between stacks, most of the time…. and also SNS but this is a legacy thing that I’m planning to remove.
c
Thanks @Sam Hulick - out of curiosity, why preface stacks with ‘dev’? Is this the environment/stage name or for something else. I thought SST or a CI/CD like Seed prepended this automatically.
Thanks @Adrián Mouly that’s helps a ton
s
yeah, it’s the stage. and I believe SST prepends that automatically
a
I don’t like the example that @Sam Hulick sent… because for me, the Functions are not strictly related to an API… could have multiple triggers at the same time.
s
the function names have the stack name attached to it.. so it doesn’t necessarily have anything to do with an API
a
In my mind, I would name those examples as…
dev-microservices-files-create
.
Yes I know.
But in your example it says
microservices-api
.
Might be just the name of the stack, but maybe the stack-name is wrong then.
Meeh, it’s not “wrong”… if works for you it’s fine.
c
Also trying to create a fully event-first architecture. Still coming up to speed on how to implement EventBridge but had it in my head it might be able to be implemented separately outside of services as something like an event hub that helps communicate things between them
a
And also I have the same problem.
@Clayton yes you can do that, maybe a general stack which creates all the event-buses.
s
🤷‍♂️
microservices-api
is the stack concerned with all HTTP API stuff. and so each API endpoint Lambda is
microservices-api-<func name>
. those funcs are never called by anything else, so I don’t see any issue with it
a
I didn’t like that too much, I wanted an stack to create the bus, which is the stack responsible of publishing events.
@Sam Hulick yes makes sense.
c
Thanks for sharing the class detail too - originally thought this was just a barrel file, but looks like I should brush up my JS class skills as well
This is all a huge help
Thanks for both sharing what you’re doing and have learned is working well
s
@Clayton all you can do is take inspiration from everyone’s setups.. as you can see, devs won’t agree on standards 😄
c
Haha. True. Trying to sort out the map to decide which route(s) may make sense to drive for where I’m trying to arrive
a
Hahahaha.
@Clayton yeah the class I’ve posted it’s just a normal class, a shell… could be also a function…. but I love OOP.
My class it’s like “stack of stacks”… I would love that concept to exists.
c
I would love that concept to also role up to something like ‘opinionated stack sets’ for common use cases as well
a
😮
Yeah I think CF it’s too simple, IMO.
Maybe it’s the foundation to build other abstractions on top.