Ignoring it completely on principal is just as bad as the people who treat it like mandatory dogma.
I’ve also had over-eager junior engineers or wannabe architects use the 12-factor article as mandatory requirements for any launch. It takes a firm and unified explanation that these are good goals to strive for, but in the real world we need to make compromises for launch and choose which aspects to delay or defer.
I have moved on a long way from the days that 12 factor was my bible, but those days completely redefined my way of developing software. I'm not exaggerating here - it completely shifted my approach.
I guess it's similar to Scrum in that way - it isn't a great end point, but if you're stuck in the old ways (i.e. the methods used before it was even a thing) then it's at least a good approach to sink your teeth into, try it out, shape your approach, and move on from there.
Basically, I'd rather see a replacement that improves on 12 factor than throwing out the book entirely.
In 2023, yes. A lot of the 12 factor methodologies became table stakes in the modern cloud era. Back when this was written "cloud" was not nearly as ubiquitous as it is now, although we were certainly headed in that direction. A lot of the comments here are viewing this through a 2023 lens and forgetting it was written in 2011.
When you discover it for the first time, you think, "huh, neat, why not use it". Before you know it, nobody can reason about your code and if you leave, nobody wants to maintain it (esp. if your test suite is not extensive).
I want to read and write the language I'm developing with, not the helper methods of some overeager developer who wanted to leave his mark on the codebase.
With the 12 factor nonsense, I see the guidance of "Dump unformatted logs into stdout and make it someone else's problem; they'll hadoop or splunk it and everyone wins." There is no magic splunk that absolve you (the developer) of generating useful data to logs, if you expect useful data out of your logs. You can't reverse "cow -> burger -> sewage" and shouldn't expect some magic hadoop to reverse entropy without a ton of work.
So -- I guess the 12 factor app dictum is fine for some trivial "I rewrote twitter in 80 lines of erlang" app, but in my opinion it is a "if we can land a man on the moon we can land a man on the sun" misstatement of complexity in actually getting things done in the real world.
Yes, if you want useful data from logs you'll need to log useful data, but this is a case where 12 factor is so successful / dominant today I don't think you even know what it's arguing against anymore.
If the logs matter -- write them to an API that retains log structure by serializing it.
If the logs don't matter, then they don't matter, but typically the logs are used for all sorts of analytics processes after the fact.
Asking someone else to parse your data is rude.
That guidance is deeply foolish; I have to assume the rest of the guidance is just as silly for anything but a toy application.
You write your logs in whatever structure you want and have something in the runtime environment (k8s, systemd, file redirection in bash whatever) forward them to the eventual storage location. I don't see the issue.
I'm supposed to just load it into memory hoping it's json or avro or whatever? Nope, errors happen; there's a limit to the number of bytes that can be sent from one place to another before the kernel may interrupt it (you're writing an application log and your runtime emits it's own debugging message; they get intermingled because they're both being written to a fifo).
Maybe this is fine (usually it's fine) but eventually it isn't fine. Use a logging library, categories your logs, maybe start off with stdout but eventually put on some big person pants and use a logging api and use the stderr/stdout for high cardinality exceptions, not "all my logs"
Use a logging library. Configure it to output well formed and categorized log messages to stdout. Let the runtime environment take that stream of data from there.
it says: A twelve-factor app never concerns itself with routing or storage of its output stream. It should not attempt to write to or manage logfiles. Instead, each running process writes its event stream, unbuffered, to stdout. During local development, the developer will view this stream in the foreground of their terminal to observe the app’s behavior.
In staging or production deploys, each process’ stream will be captured by the execution environment, collated together with all other streams from the app, and routed to one or more final destinations for viewing and long-term archival. These archival destinations are not visible to or configurable by the app, and instead are completely managed by the execution environment. Open-source log routers (such as Logplex and Fluentd) are available for this purpose.
The event stream for an app can be routed to a file, or watched via realtime tail in a terminal. Most significantly, the stream can be sent to a log indexing and analysis system such as Splunk, or a general-purpose data warehousing system such as Hadoop/Hive. These systems allow for great power and flexibility for introspecting an app’s behavior over time, including:
This is, at scale, utter horseshit. If it said "do what's expedient, but use a library and be flexible in how you generate logs, but for goodness sake use any of the publicly available libraries to be expedient now and reliable and flexible later" I'd shrug and move on, but it's just absolute garbage. "Do a shitty job and someone else will fix it for you" is not good advice, even if it lets you get to market quickly.
Right. It's not telling you anything about whether to use a library or not. All it's talking about is where you output your logging streams to, not about how you produce or format those streams. Is it bad advice because it doesn't tell you you should wear sunscreen when you go outside in summer?
(FWIW I haven't seen any logging library add enough value to be worthwhile. Eventually graduating to structured event logs is a good idea, but having started with a logging library doesn't actually get you any closer to that).
A more reasonable reading of 12 factor is to see that since it suggests that the output streams should be gathered up from multiple running instances of the application, and collated together in a system like splunk, that it behooves you as a 12 factor app developer to build your app such that your output stream is amenable to that approach.
I.e., that your output is a stream of structured serialized data.
You haven't clarified what you think is a better practice than this.
The words don't suggest anything else. Maybe your experience suggests maybe you should use a library and reserve the ability to serialize that data to a proper api if necessary, but that's you not the words in the 12 factor app, and some large subset of people just do the minimum necessary to get the ticket off their queue, and if that means "printf log" that's what this advice in this suggests they'll do. It's splunk's problem now!
And my advice is "use a damned logging library; understand the distinction between using a networking stack and API that manages abstractions like event size and retrying and such and stdout, which offers none of that."
So now, when I see a reference to "12 factor app" I assume "ah, a hello world app from someone who's going to leave and let someone else figure out how to make it work in the real world at real loads with real regulatory or compliance needs"
In other words, for me, it's a shibboleth for "toy" or "unserious piece of shit"
There may, in fact, be parts of the guidance that aren't deeply incorrect. But anyone who points at it as a way to do things, without caveats, is suspect.
The idea of 12 factor is to define a reasonable interface for your application. The environment doesn't need to worry about providing interfaces to logging services or collecting files from a custom directory, or making sure the application isn't going to fill the disk with log output - if the app is 12 factor, the only thing the environment needs to do is collect stdout.
As a 12 factor app, write such that what you put on stdout is useful for that purpose.
As a system hosting 12 factor apps, collect stdout and put it somewhere useful.
As a developer of a 12 factor app, when you want to see your log output, go wherever the environment puts it and look there.
That's a useful contract that works at scale. Not sure why you think it doesn't.
I'd love to know what other things you saw one part of and then dismissed fully without further investigation.
Are iPhones unacceptable because they suggest you set a 4 digit pin for access? Aeroplane safety demonstrations? Languages with gendered verbs?
It is the least controversial and most broadly beneficial of the 12 factors.
Why do you think it’s foolish?
As that someone else, who often has bug reports like "why aren't my log events all in one record in my thing? Because you filled your stdout with newlines!" "Why did my message vanish? It was important!" "because it's malformed json because your runtime had an error; it's over there instead of over here."
Programming's a stack of details; all of which matter. Log using a logging API where available; use stdout/stderr for exception logging only, if at all possible. If you want your logging to be useful, think carefully about how and what you log.
All it means is to let someone else (other than the program itself) figure out how to get the log messages (whatever you decide they should be) from your process (running wherever it is) to wherever you want to have those logs for inspection.
Do not hardcode into your application the assumption that they are written to a file or sent to a port.
In your application, write them to stdout.
In local dev, stdout will probably go to an interactive console. In a container running in a cloud hosted cluster it will probably go to a networked log aggregator that collects it all into an indexed time oriented data store along with other logs from other running instances.
Because you used stdout, that’s easy to do.
If you wrote them to a file whose name your application manages and changes itself to manage log rotation… either of those is hard to do.
Thank you! This is the same thing people miss when they read things like the Agile Manifesto, or about DevOps, or even architectural choices like React's original pitch for one-way data binding - or, dare I say, microservices.
You can read these things today, and see flaws - holes in the argument, mistaken assumptions, or misread them as claiming to be superior to things that have been developed since. No - to understand what they are talking about you need to know what was current common knowledge or accepted wisdom in the world when they were written.
I can give an example. The part about sticky sessions is good generic advice for someone building generic web services, but there are situations where sticky session-like functionality or sharding-like behavior might be a better choice. Anyone adhering literally to the 12-factor guide would get hung up on trying to move that data to redis or memcached:
> Some web systems rely on “sticky sessions” – that is, caching user session data in memory of the app’s process and expecting future requests from the same visitor to be routed to the same process. Sticky sessions are a violation of twelve-factor and should never be used or relied upon. Session state data is a good candidate for a datastore that offers time-expiration, such as Memcached or Redis.
The guide also has a strong preference for languages like Ruby, Perl, and Python. There’s even a quip about how 12-factor prefers languages with a REPL, which in the wrong hands becomes an argument against using Rust or other languages.
People who think the entire world is simple CRUD web apps tend to think that guides like this are completely universal. It’s a good guide for people making common web apps, but it’s not a perfect methodology for every backend service.
That's the very first point they make:
> In the modern era, software is commonly delivered as a service: called web apps, or software-as-a-service. The twelve-factor app is a methodology for building software-as-a-service apps that...
Anything not web app/SaaS they express no opinion on.
You didn't actually give an complete example. When are sticky sessions a better choice than persistence?
12FA is not a single box that is to be checked. It can and in most cases probably should be implemented over time as the product matures, taking each point, point by point (and maybe even breaking those up) and adding that into the product. If you've done good engineering up front (abstractions and interfaces where it makes sense, not hard coding everything) this should not be an issue.
inb4 YAGNI: this is just as abused as 12FA.
EDIT: the biggest thing 12FA is missing are concrete examples that junior engineers can reference.
I've learned to take issues like that in good faith. Why are they raising an issue? Is the existing process not clear? Is there a deficiency in it? Is there a lack of reliability? If reasonable concerns are found, the process can change (and the documentation is to be updated).
This has its own drawbacks. I worked for a company, in which Process Was God, and Thou Shalt Do Only That Which God Has Proclaimed Good.
It worked most of the time, but made it very, very difficult to introduce flexibility and orthogonal approaches.
There's really no way to duplicate the results of experienced, cohesive teams of high-functioning engineers, with process. We can get similar results, in many ways, but there's always a price to be paid.
T. A. N. S. T. A. A. F. L.
Yeah, I work in ops^W platform.
I've found it pretty useful in practice. I don't see why it's much more useful to those people than it has been for me.
Being able to point management at this can be really useful.
For most of us here, it is 99% common sense.
There are gold nuggets in many of this style of "manifesto". It just takes a handful of people treating it as dogma to stink them up.
Hard to believe that treating best practices as strict rules would not turn out to be best practice, isn't it?